From dda40ca71a669d7ba39261cb94d78772f5803b42 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Wed, 11 May 2005 19:16:19 +0000 Subject: [PATCH] Use a GtkAlignment rather than a GtkDrawingArea to draw the swatch in to 2005-05-11 Owen Taylor * gtk/gtkcolorbutton.c: Use a GtkAlignment rather than a GtkDrawingArea to draw the swatch in to avoid having an extraneous window. * gtk/gtkcolorsel.c (color_sample_draw_sample): Actually se tthe color when !has_opacity. 2005-05-10 Owen Taylor * gdk/gdkcairo.[ch] gdk/gdkcolor.[ch] gdk/Makefile.am: Add source files for Cairo convenience functionality. * gdk/gdkcairo.h (gdk_cairo_rectangle, gdk_cairo_region): Add a convenience functions to add GdkRectangle, GdkRegion to a cairo path. * gdk/gdkwindow.c gdk/gdkgc.c gtk/gtkcolorsel.c gtk/gtkiconview.c gtk/gtkstyle.c: Use gdk_cairo_rectangle/region(). * gdk/gdkcairo.[ch] gdk/gdkdrawable.h gdk/gdkdraw.c: Rename gdk_drawable_create_cairo_context() to gdk_cairo_create(). * gdk/gdkcairo.c gdk/gdkpixbuf.h gdk/gdkpixbuf-render.c: Rename gdk_pixbuf_set_as_cairo_source() to gdk_cairo_set_source_pixbuf(). * gdk/gdkdraw.c gdk/gdkpango.c gtk/gtkcolorsel.c gtk/gtkhruler.c gtk/gtkhsv.c gtk/gtkiconview.c gtk/gtkstyle.c gtk/gtkvruler.c: Adjust for renames. * gdk/gdk.symbols: Update. * gtk/gtkwidget.c (gtk_widget_queue_shallow_draw): Fix coordinate system problem that was causing the wrong portions to be invalidated. * gtk/gtkcellrenderer.c (gtk_cell_renderer_render) gtk/gtkcellrendererpixbuf.c (gtk_cell_renderer_pixbuf_render) gtk/gtkcellrendererprogress.c (gtk_cell_renderer_progress_render) gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_render) gtk/gtkcellview.c (gtk_cell_view_expose) gtk/gtkdnd.c (gtk_drag_highlight_expose) gtk/gtkentry.c (gtk_entry_draw_text) gtk/gtktextview.c (text_window_invalidate_rect): Some cairoization. * gtk/gtkcalendar.[ch]: Beat into something roughly resembling GTK+ style ... use instance-private data and standard names for private structure, etc. Move function docs inline. * gtk/gtkcalendar.[ch]: Switch to drawing everything in expose. Switch drawing to Cairo. * gtk/gtkcalendar.c (gtk_calendar_freeze): Deprecate gtk_calendar_freeze/thaw --- ChangeLog | 55 + ChangeLog.pre-2-10 | 55 + ChangeLog.pre-2-8 | 55 + docs/reference/gtk/tmpl/gtkcalendar.sgml | 63 +- gdk/Makefile.am | 4 +- gdk/gdk.h | 1 + gdk/gdk.symbols | 13 +- gdk/gdkcairo.c | 221 ++ gdk/gdkcairo.h | 45 + gdk/gdkcolor.c | 20 - gdk/gdkcolor.h | 3 - gdk/gdkdraw.c | 30 +- gdk/gdkdrawable.h | 2 - gdk/gdkgc.c | 16 +- gdk/gdkpango.c | 2 +- gdk/gdkpixbuf-render.c | 99 - gdk/gdkpixbuf.h | 5 - gdk/gdkwindow.c | 19 +- gtk/gtk.symbols | 6 +- gtk/gtkcalendar.c | 4149 +++++++++++----------- gtk/gtkcalendar.h | 11 +- gtk/gtkcellrenderer.c | 20 +- gtk/gtkcellrendererpixbuf.c | 20 +- gtk/gtkcellrendererprogress.c | 25 +- gtk/gtkcellrenderertext.c | 37 +- gtk/gtkcellview.c | 23 +- gtk/gtkcolorbutton.c | 39 +- gtk/gtkcolorsel.c | 33 +- gtk/gtkdnd.c | 16 +- gtk/gtkentry.c | 57 +- gtk/gtkhruler.c | 4 +- gtk/gtkhsv.c | 2 +- gtk/gtkiconview.c | 27 +- gtk/gtkstyle.c | 26 +- gtk/gtktextview.c | 12 +- gtk/gtkvruler.c | 4 +- gtk/gtkwidget.c | 18 + tests/testcairo.c | 2 +- 38 files changed, 2655 insertions(+), 2584 deletions(-) create mode 100644 gdk/gdkcairo.c create mode 100644 gdk/gdkcairo.h diff --git a/ChangeLog b/ChangeLog index e76a646502..9dd0685777 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,58 @@ +2005-05-11 Owen Taylor + + * gtk/gtkcolorbutton.c: Use a GtkAlignment rather than a GtkDrawingArea + to draw the swatch in to avoid having an extraneous window. + + * gtk/gtkcolorsel.c (color_sample_draw_sample): Actually se tthe + color when !has_opacity. + +2005-05-10 Owen Taylor + + * gdk/gdkcairo.[ch] gdk/gdkcolor.[ch] gdk/Makefile.am: Add source + files for Cairo convenience functionality. + + * gdk/gdkcairo.h (gdk_cairo_rectangle, gdk_cairo_region): Add a + convenience functions to add GdkRectangle, GdkRegion to a cairo path. + + * gdk/gdkwindow.c gdk/gdkgc.c gtk/gtkcolorsel.c gtk/gtkiconview.c + gtk/gtkstyle.c: Use gdk_cairo_rectangle/region(). + + * gdk/gdkcairo.[ch] gdk/gdkdrawable.h gdk/gdkdraw.c: Rename + gdk_drawable_create_cairo_context() to gdk_cairo_create(). + + * gdk/gdkcairo.c gdk/gdkpixbuf.h gdk/gdkpixbuf-render.c: + Rename gdk_pixbuf_set_as_cairo_source() to + gdk_cairo_set_source_pixbuf(). + + * gdk/gdkdraw.c gdk/gdkpango.c gtk/gtkcolorsel.c gtk/gtkhruler.c + gtk/gtkhsv.c gtk/gtkiconview.c gtk/gtkstyle.c gtk/gtkvruler.c: + Adjust for renames. + + * gdk/gdk.symbols: Update. + + * gtk/gtkwidget.c (gtk_widget_queue_shallow_draw): Fix + coordinate system problem that was causing the wrong portions + to be invalidated. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_render) + gtk/gtkcellrendererpixbuf.c (gtk_cell_renderer_pixbuf_render) + gtk/gtkcellrendererprogress.c (gtk_cell_renderer_progress_render) + gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_render) + gtk/gtkcellview.c (gtk_cell_view_expose) + gtk/gtkdnd.c (gtk_drag_highlight_expose) + gtk/gtkentry.c (gtk_entry_draw_text) + gtk/gtktextview.c (text_window_invalidate_rect): Some cairoization. + + * gtk/gtkcalendar.[ch]: Beat into something roughly resembling + GTK+ style ... use instance-private data and standard names for + private structure, etc. Move function docs inline. + + * gtk/gtkcalendar.[ch]: Switch to drawing everything in + expose. Switch drawing to Cairo. + + * gtk/gtkcalendar.c (gtk_calendar_freeze): Deprecate + gtk_calendar_freeze/thaw + 2005-05-10 Tor Lillqvist * gdk/win32/gdkproperty-win32.c (gdk_screen_get_setting): Check diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index e76a646502..9dd0685777 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,58 @@ +2005-05-11 Owen Taylor + + * gtk/gtkcolorbutton.c: Use a GtkAlignment rather than a GtkDrawingArea + to draw the swatch in to avoid having an extraneous window. + + * gtk/gtkcolorsel.c (color_sample_draw_sample): Actually se tthe + color when !has_opacity. + +2005-05-10 Owen Taylor + + * gdk/gdkcairo.[ch] gdk/gdkcolor.[ch] gdk/Makefile.am: Add source + files for Cairo convenience functionality. + + * gdk/gdkcairo.h (gdk_cairo_rectangle, gdk_cairo_region): Add a + convenience functions to add GdkRectangle, GdkRegion to a cairo path. + + * gdk/gdkwindow.c gdk/gdkgc.c gtk/gtkcolorsel.c gtk/gtkiconview.c + gtk/gtkstyle.c: Use gdk_cairo_rectangle/region(). + + * gdk/gdkcairo.[ch] gdk/gdkdrawable.h gdk/gdkdraw.c: Rename + gdk_drawable_create_cairo_context() to gdk_cairo_create(). + + * gdk/gdkcairo.c gdk/gdkpixbuf.h gdk/gdkpixbuf-render.c: + Rename gdk_pixbuf_set_as_cairo_source() to + gdk_cairo_set_source_pixbuf(). + + * gdk/gdkdraw.c gdk/gdkpango.c gtk/gtkcolorsel.c gtk/gtkhruler.c + gtk/gtkhsv.c gtk/gtkiconview.c gtk/gtkstyle.c gtk/gtkvruler.c: + Adjust for renames. + + * gdk/gdk.symbols: Update. + + * gtk/gtkwidget.c (gtk_widget_queue_shallow_draw): Fix + coordinate system problem that was causing the wrong portions + to be invalidated. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_render) + gtk/gtkcellrendererpixbuf.c (gtk_cell_renderer_pixbuf_render) + gtk/gtkcellrendererprogress.c (gtk_cell_renderer_progress_render) + gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_render) + gtk/gtkcellview.c (gtk_cell_view_expose) + gtk/gtkdnd.c (gtk_drag_highlight_expose) + gtk/gtkentry.c (gtk_entry_draw_text) + gtk/gtktextview.c (text_window_invalidate_rect): Some cairoization. + + * gtk/gtkcalendar.[ch]: Beat into something roughly resembling + GTK+ style ... use instance-private data and standard names for + private structure, etc. Move function docs inline. + + * gtk/gtkcalendar.[ch]: Switch to drawing everything in + expose. Switch drawing to Cairo. + + * gtk/gtkcalendar.c (gtk_calendar_freeze): Deprecate + gtk_calendar_freeze/thaw + 2005-05-10 Tor Lillqvist * gdk/win32/gdkproperty-win32.c (gdk_screen_get_setting): Check diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index e76a646502..9dd0685777 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,58 @@ +2005-05-11 Owen Taylor + + * gtk/gtkcolorbutton.c: Use a GtkAlignment rather than a GtkDrawingArea + to draw the swatch in to avoid having an extraneous window. + + * gtk/gtkcolorsel.c (color_sample_draw_sample): Actually se tthe + color when !has_opacity. + +2005-05-10 Owen Taylor + + * gdk/gdkcairo.[ch] gdk/gdkcolor.[ch] gdk/Makefile.am: Add source + files for Cairo convenience functionality. + + * gdk/gdkcairo.h (gdk_cairo_rectangle, gdk_cairo_region): Add a + convenience functions to add GdkRectangle, GdkRegion to a cairo path. + + * gdk/gdkwindow.c gdk/gdkgc.c gtk/gtkcolorsel.c gtk/gtkiconview.c + gtk/gtkstyle.c: Use gdk_cairo_rectangle/region(). + + * gdk/gdkcairo.[ch] gdk/gdkdrawable.h gdk/gdkdraw.c: Rename + gdk_drawable_create_cairo_context() to gdk_cairo_create(). + + * gdk/gdkcairo.c gdk/gdkpixbuf.h gdk/gdkpixbuf-render.c: + Rename gdk_pixbuf_set_as_cairo_source() to + gdk_cairo_set_source_pixbuf(). + + * gdk/gdkdraw.c gdk/gdkpango.c gtk/gtkcolorsel.c gtk/gtkhruler.c + gtk/gtkhsv.c gtk/gtkiconview.c gtk/gtkstyle.c gtk/gtkvruler.c: + Adjust for renames. + + * gdk/gdk.symbols: Update. + + * gtk/gtkwidget.c (gtk_widget_queue_shallow_draw): Fix + coordinate system problem that was causing the wrong portions + to be invalidated. + + * gtk/gtkcellrenderer.c (gtk_cell_renderer_render) + gtk/gtkcellrendererpixbuf.c (gtk_cell_renderer_pixbuf_render) + gtk/gtkcellrendererprogress.c (gtk_cell_renderer_progress_render) + gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_render) + gtk/gtkcellview.c (gtk_cell_view_expose) + gtk/gtkdnd.c (gtk_drag_highlight_expose) + gtk/gtkentry.c (gtk_entry_draw_text) + gtk/gtktextview.c (text_window_invalidate_rect): Some cairoization. + + * gtk/gtkcalendar.[ch]: Beat into something roughly resembling + GTK+ style ... use instance-private data and standard names for + private structure, etc. Move function docs inline. + + * gtk/gtkcalendar.[ch]: Switch to drawing everything in + expose. Switch drawing to Cairo. + + * gtk/gtkcalendar.c (gtk_calendar_freeze): Deprecate + gtk_calendar_freeze/thaw + 2005-05-10 Tor Lillqvist * gdk/win32/gdkproperty-win32.c (gdk_screen_get_setting): Check diff --git a/docs/reference/gtk/tmpl/gtkcalendar.sgml b/docs/reference/gtk/tmpl/gtkcalendar.sgml index cde6a8c859..1a2727d4d1 100644 --- a/docs/reference/gtk/tmpl/gtkcalendar.sgml +++ b/docs/reference/gtk/tmpl/gtkcalendar.sgml @@ -27,11 +27,6 @@ gtk_calendar_set_display_options(). The selected date can be retrieved from a #GtkCalendar using gtk_calendar_get_date(). - -If performing many 'mark' operations, the calendar can be frozen to prevent -flicker, using gtk_calendar_freeze(), and 'thawed' again using -gtk_calendar_thaw(). - @@ -165,59 +160,52 @@ These options can be used to influence the display and behaviour of a #GtkCalend -Creates a new calendar, with the current date being selected. -@Returns: a #GtkCalendar. +@Returns: -Shifts the calendar to a different month. -@calendar: a #GtkCalendar. -@month: a month number between 0 and 11. -@year: the year the month is in. -@Returns: %TRUE. +@calendar: +@month: +@year: +@Returns: -Selects a day from the current month. -@calendar: a #GtkCalendar. -@day: the day number between 1 and 31, or 0 to unselect - the currently selected day. +@calendar: +@day: -Places a visual marker on a particular day. -@calendar: a #GtkCalendar. -@day: the day number to mark between 1 and 31. -@Returns: %TRUE. +@calendar: +@day: +@Returns: -Removes the visual marker from a particular day. -@calendar: a #GtkCalendar. -@day: the day number to unmark between 1 and 31. -@Returns: %TRUE. +@calendar: +@day: +@Returns: -Remove all visual markers. -@calendar: a #GtkCalendar. +@calendar: @@ -240,39 +228,34 @@ Remove all visual markers. -Sets display options (whether to display the heading and the month headings). -@calendar: a #GtkCalendar. -@flags: the display options to set. -@Deprecated: Use gtk_calendar_set_display_options() instead +@calendar: +@flags: +@Deprecated: -Obtains the selected date from a #GtkCalendar. -@calendar: a #GtkCalendar. -@year: location to store the year number. -@month: location to store the month number (between 0 and 11). -@day: location to store the day number (between 1 and 31). +@calendar: +@year: +@month: +@day: -Locks the display of the calendar until it is thawed with gtk_calendar_thaw(). -@calendar: a #GtkCalendar. +@calendar: -Defrosts a calendar; all the changes made since the last -gtk_calendar_freeze() are displayed. -@calendar: a #GtkCalendar. +@calendar: diff --git a/gdk/Makefile.am b/gdk/Makefile.am index a66938a7a5..0fcb35c865 100644 --- a/gdk/Makefile.am +++ b/gdk/Makefile.am @@ -50,6 +50,7 @@ LDADD = \ # gdk_public_h_sources = \ gdk.h \ + gdkcairo.h \ gdkcolor.h \ gdkcursor.h \ gdkdisplay.h \ @@ -85,6 +86,7 @@ gdk_headers = \ gdk_c_sources = \ gdk.c \ + gdkcairo.c \ gdkcolor.c \ gdkcursor.c \ gdkdisplay.c \ @@ -240,7 +242,7 @@ stamp-gdkenumtypes.h: @REBUILD@ $(gdk_public_h_sources) Makefile gdkenumtypes.c: @REBUILD@ $(gdk_public_h_sources) Makefile ( cd $(srcdir) && glib-mkenums \ --fhead "#define GDK_ENABLE_BROKEN\n#include \"gdk.h\"\n#include \"gdkalias.h\"\n" \ - --fprod "\n/* enumerations from \"@filename@\" */" \ + --fprod "\n/* enumerations from \"@filename@\" */" \ --ftail "\n#define __GDK_ENUM_TYPES_C__\n#include \"gdkaliasdef.c\"\n" \ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ diff --git a/gdk/gdk.h b/gdk/gdk.h index bbc1967dfc..4cbe1068e5 100644 --- a/gdk/gdk.h +++ b/gdk/gdk.h @@ -27,6 +27,7 @@ #ifndef __GDK_H__ #define __GDK_H__ +#include #include #include #include diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index 93448836dc..8e70365ba0 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -288,6 +288,16 @@ gdk_fontset_load_for_display #endif #endif +#if IN_HEADER(__GDK_CAIRO_H__) +#if IN_FILE(__GDK_CAIRO_C__) +gdk_cairo_create +gdk_cairo_set_source_color +gdk_cairo_set_source_pixbuf +gdk_cairo_rectangle +gdk_cairo_region +#endif +#endif + #if IN_HEADER(__GDK_COLOR_H__) #if IN_FILE(__GDK_COLOR_C__) #ifndef GDK_DISABLE_DEPRECATED @@ -301,7 +311,6 @@ gdk_color_equal gdk_color_free gdk_color_get_type G_GNUC_CONST gdk_color_hash -gdk_cairo_set_source_color gdk_colormap_alloc_color gdk_colormap_get_system gdk_colormap_get_visual @@ -510,7 +519,6 @@ gdk_drag_get_protocol #if IN_HEADER(__GDK_DRAWABLE_H__) #if IN_FILE(__GDK_DRAW_C__) -gdk_drawable_create_cairo_context gdk_drawable_copy_to_image gdk_drawable_get_clip_region gdk_drawable_get_colormap @@ -853,7 +861,6 @@ gdk_pixbuf_get_from_image gdk_pixbuf_render_pixmap_and_mask gdk_pixbuf_render_pixmap_and_mask_for_colormap gdk_pixbuf_render_threshold_alpha -gdk_pixbuf_set_as_cairo_source #ifndef GDK_DISABLE_DEPRECATED gdk_pixbuf_render_to_drawable gdk_pixbuf_render_to_drawable_alpha diff --git a/gdk/gdkcairo.c b/gdk/gdkcairo.c new file mode 100644 index 0000000000..4e498546fa --- /dev/null +++ b/gdk/gdkcairo.c @@ -0,0 +1,221 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2005 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "gdkcairo.h" +#include "gdkdrawable.h" +#include "gdkinternals.h" +#include "gdkregion-generic.h" +#include "gdkalias.h" + +/** + * gdk_cairo_create: + * @drawable: a #GdkDrawable + * + * Creates a Cairo context for drawing to @drawable. + * + * Return value: A newly created Cairo context. Free with + * cairo_destroy() when you are done drawing. + * + * Since: 2.10 + **/ +cairo_t * +gdk_cairo_create (GdkDrawable *drawable) +{ + cairo_surface_t *surface; + cairo_t *cr; + + g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); + + surface = _gdk_drawable_ref_cairo_surface (drawable); + cr = cairo_create (surface); + cairo_surface_destroy (surface); + + return cr; +} + +/** + * gdk_cairo_set_source_color: + * @cr: a #cairo_t + * @color: a #GdkColor + * + * Sets the specified #GdkColor as the source color of @cr. + * + * Since: 2.8 + **/ +void +gdk_cairo_set_source_color (cairo_t *cr, + GdkColor *color) +{ + g_return_if_fail (cr != NULL); + g_return_if_fail (color != NULL); + + cairo_set_source_rgb (cr, + color->red / 65535., + color->green / 65535., + color->blue / 65535.); +} + +/** + * gdk_cairo_rectangle: + * @cr: a #cairo_t + * @rectangle: a #GdkRectangle + * + * Adds the given rectangle to the current path of @cr. + **/ +void +gdk_cairo_rectangle (cairo_t *cr, + GdkRectangle *rectangle) +{ + g_return_if_fail (cr != NULL); + g_return_if_fail (rectangle != NULL); + + cairo_rectangle (cr, + rectangle->x, rectangle->y, + rectangle->width, rectangle->height); +} + +/** + * gdk_cairo_region: + * @cr: a #cairo_t + * @region: a #GdkRegion + * + * Adds the given region to the current path of @cr. + **/ +void +gdk_cairo_region (cairo_t *cr, + GdkRegion *region) +{ + GdkRegionBox *boxes; + gint n_boxes, i; + + g_return_if_fail (cr != NULL); + g_return_if_fail (region != NULL); + + boxes = region->rects; + n_boxes = region->numRects; + + for (i = 0; i < n_boxes; i++) + cairo_rectangle (cr, + boxes[i].x1, + boxes[i].y1, + boxes[i].x2 - boxes[i].x1, + boxes[i].y2 - boxes[i].y1); +} + +/** + * gdk_cairo_set_source_pixbuf: + * @cr: a #Cairo context + * @pixbuf: a #GdkPixbuf + * @pixbuf_x: X coordinate of location to place upper left corner of @pixbuf + * @pixbuf_y: Y coordinate of location to place upper left corner of @pixbuf + * + * Sets the given pixbuf as the source pattern for the Cairo context. + * The pattern has an extend mode of %CAIRO_EXTEND_NONE and is aligned + * so that the origin of @pixbuf is @pixbuf_x, @pixbuf_y + **/ +void +gdk_cairo_set_source_pixbuf (cairo_t *cr, + GdkPixbuf *pixbuf, + double pixbuf_x, + double pixbuf_y) +{ + gint width = gdk_pixbuf_get_width (pixbuf); + gint height = gdk_pixbuf_get_height (pixbuf); + guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf); + int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + int n_channels = gdk_pixbuf_get_n_channels (pixbuf); + guchar *cairo_pixels; + cairo_format_t format; + cairo_surface_t *surface; + static const cairo_user_data_key_t key; + int j; + + if (n_channels == 3) + format = CAIRO_FORMAT_RGB24; + else + format = CAIRO_FORMAT_ARGB32; + + cairo_pixels = g_malloc (4 * width * height); + surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels, + format, + width, height, 4 * width); + cairo_surface_set_user_data (surface, &key, + cairo_pixels, (cairo_destroy_func_t)g_free); + + for (j = height; j; j--) + { + guchar *p = gdk_pixels; + guchar *q = cairo_pixels; + + if (n_channels == 3) + { + guchar *end = p + 3 * width; + + while (p < end) + { +#if G_BYTE_ORDER == GDK_LSB_FIRST + q[0] = p[2]; + q[1] = p[1]; + q[2] = p[2]; +#else + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; +#endif + p += 3; + q += 4; + } + } + else + { + guchar *end = p + 4 * width; + guint t1,t2,t3; + +#define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END + + while (p < end) + { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + MULT(q[0], p[2], p[3], t1); + MULT(q[1], p[1], p[3], t2); + MULT(q[2], p[0], p[3], t3); + q[3] = p[3]; +#else + q[0] = p[3]; + MULT(q[1], p[0], p[3], t1); + MULT(q[2], p[1], p[3], t2); + MULT(q[3], p[2], p[3], t3); +#endif + + p += 4; + q += 4; + } + +#undef MULT + } + + gdk_pixels += gdk_rowstride; + cairo_pixels += 4 * width; + } + + cairo_set_source_surface (cr, surface, pixbuf_x, pixbuf_y); +} + +#define __GDK_CAIRO_C__ +#include "gdkaliasdef.c" diff --git a/gdk/gdkcairo.h b/gdk/gdkcairo.h new file mode 100644 index 0000000000..3918f2381e --- /dev/null +++ b/gdk/gdkcairo.h @@ -0,0 +1,45 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2005 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GDK_CAIRO_H__ +#define __GDK_CAIRO_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +cairo_t *gdk_cairo_create (GdkDrawable *drawable); + +void gdk_cairo_set_source_color (cairo_t *cr, + GdkColor *color); +void gdk_cairo_set_source_pixbuf (cairo_t *cr, + GdkPixbuf *pixbuf, + double pixbuf_x, + double pixbuf_y); + +void gdk_cairo_rectangle (cairo_t *cr, + GdkRectangle *rectangle); +void gdk_cairo_region (cairo_t *cr, + GdkRegion *region); + +G_END_DECLS + +#endif /* __GDK_CAIRO_H__ */ diff --git a/gdk/gdkcolor.c b/gdk/gdkcolor.c index 27bdf19460..d2a4a55cab 100644 --- a/gdk/gdkcolor.c +++ b/gdk/gdkcolor.c @@ -371,25 +371,5 @@ gdk_colormap_get_system (void) return gdk_screen_get_system_colormap (gdk_screen_get_default ()); } -/** - * gdk_cairo_set_source_color: - * @cr: a #cairo_t - * @color: a #GdkColor - * - * Convenience function to set the specified GdkColor as the - * source color of the given Cairo context. - * - * Since: 2.8 - **/ -void -gdk_cairo_set_source_color (cairo_t *cr, - GdkColor *color) -{ - cairo_set_source_rgb (cr, - color->red / 65535., - color->green / 65535., - color->blue / 65535.); -} - #define __GDK_COLOR_C__ #include "gdkaliasdef.c" diff --git a/gdk/gdkcolor.h b/gdk/gdkcolor.h index bbf7bd83f4..4d8a7e6df2 100644 --- a/gdk/gdkcolor.h +++ b/gdk/gdkcolor.h @@ -111,9 +111,6 @@ gboolean gdk_color_equal (const GdkColor *colora, GType gdk_color_get_type (void) G_GNUC_CONST; -void gdk_cairo_set_source_color (cairo_t *cr, - GdkColor *color); - /* The following functions are deprecated */ #ifndef GDK_DISABLE_DEPRECATED void gdk_colors_store (GdkColormap *colormap, diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c index f956a5bedd..93e3e9f8f3 100644 --- a/gdk/gdkdraw.c +++ b/gdk/gdkdraw.c @@ -879,7 +879,7 @@ real_draw_glyphs (GdkDrawable *drawable, { cairo_t *cr; - cr = gdk_drawable_create_cairo_context (drawable); + cr = gdk_cairo_create (drawable); _gdk_gc_update_context (gc, cr, NULL, NULL); if (matrix) @@ -1003,7 +1003,7 @@ gdk_draw_trapezoids (GdkDrawable *drawable, g_return_if_fail (GDK_IS_GC (gc)); g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL); - cr = gdk_drawable_create_cairo_context (drawable); + cr = gdk_cairo_create (drawable); _gdk_gc_update_context (gc, cr, NULL, NULL); for (i = 0; i < n_trapezoids; i++) @@ -1285,32 +1285,6 @@ _gdk_drawable_ref_cairo_surface (GdkDrawable *drawable) return GDK_DRAWABLE_GET_CLASS (drawable)->ref_cairo_surface (drawable); } -/** - * gdk_drawable_create_cairo_context: - * @drawable: a #GdkDrawable - * - * Creates a Cairo context for drawing to @drawable. - * - * Return value: A newly created Cairo context. Free with - * cairo_destroy() when you are done drawing. - * - * Since: 2.10 - **/ -cairo_t * -gdk_drawable_create_cairo_context (GdkDrawable *drawable) -{ - cairo_surface_t *surface; - cairo_t *cr; - - g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); - - surface = _gdk_drawable_ref_cairo_surface (drawable); - cr = cairo_create (surface); - cairo_surface_destroy (surface); - - return cr; -} - static void composite (guchar *src_buf, gint src_rowstride, diff --git a/gdk/gdkdrawable.h b/gdk/gdkdrawable.h index 19344954f1..1e9194e4d1 100644 --- a/gdk/gdkdrawable.h +++ b/gdk/gdkdrawable.h @@ -391,8 +391,6 @@ GdkImage *gdk_drawable_copy_to_image (GdkDrawable *drawable, GdkRegion *gdk_drawable_get_clip_region (GdkDrawable *drawable); GdkRegion *gdk_drawable_get_visible_region (GdkDrawable *drawable); -cairo_t *gdk_drawable_create_cairo_context (GdkDrawable *drawable); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c index 72115eec27..b29fecb608 100644 --- a/gdk/gdkgc.c +++ b/gdk/gdkgc.c @@ -27,10 +27,10 @@ #include #include +#include "gdkcairo.h" #include "gdkgc.h" #include "gdkinternals.h" #include "gdkpixmap.h" -#include "gdkregion-generic.h" #include "gdkrgb.h" #include "gdkprivate.h" #include "gdkalias.h" @@ -1225,21 +1225,13 @@ _gdk_gc_update_context (GdkGC *gc, cairo_reset_clip (cr); if (priv->clip_region) { - GdkRegionBox *boxes = priv->clip_region->rects; - gint n_boxes = priv->clip_region->numRects; - int i; - cairo_save (cr); cairo_identity_matrix (cr); - + cairo_translate (cr, gc->clip_x_origin, gc->clip_y_origin); + cairo_new_path (cr); - for (i=0; i < n_boxes; i++) - cairo_rectangle (cr, - boxes[i].x1 + gc->clip_x_origin, - boxes[i].y1 + gc->clip_y_origin, - boxes[i].x2 - boxes[i].x1, - boxes[i].y2 - boxes[i].y1); + gdk_cairo_region (cr, priv->clip_region); cairo_restore (cr); diff --git a/gdk/gdkpango.c b/gdk/gdkpango.c index 4a266762b5..a160511dc7 100644 --- a/gdk/gdkpango.c +++ b/gdk/gdkpango.c @@ -141,7 +141,7 @@ get_cairo_context (GdkPangoRenderer *gdk_renderer, { const PangoMatrix *matrix; - priv->cr = gdk_drawable_create_cairo_context (priv->drawable); + priv->cr = gdk_cairo_create (priv->drawable); matrix = pango_renderer_get_matrix (renderer); if (matrix) diff --git a/gdk/gdkpixbuf-render.c b/gdk/gdkpixbuf-render.c index d8eda5eb69..31dcb62cc8 100644 --- a/gdk/gdkpixbuf-render.c +++ b/gdk/gdkpixbuf-render.c @@ -329,105 +329,6 @@ gdk_pixbuf_render_pixmap_and_mask_for_colormap (GdkPixbuf *pixbuf, } } -/** - * gdk_pixbuf_set_as_cairo_source: - * @pixbuf: a #GdkPixbuf - * @cr: a #Cairo context - * @pixbuf_x: X coordinate of location to place upper left corner of @pixbuf - * @pixbuf_y: Y coordinate of location to place upper left corner of @pixbuf - * - * Sets the given pixbuf as the source pattern for the Cairo context. - * The pattern has an extend mode of %CAIRO_EXTEND_NONE and is aligned - * so that the origin of @pixbuf is @pixbuf_x, @pixbuf_y - **/ -void -gdk_pixbuf_set_as_cairo_source (GdkPixbuf *pixbuf, - cairo_t *cr, - double pixbuf_x, - double pixbuf_y) -{ - gint width = gdk_pixbuf_get_width (pixbuf); - gint height = gdk_pixbuf_get_height (pixbuf); - guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf); - int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf); - int n_channels = gdk_pixbuf_get_n_channels (pixbuf); - guchar *cairo_pixels; - cairo_format_t format; - cairo_surface_t *surface; - static const cairo_user_data_key_t key; - int j; - - if (n_channels == 3) - format = CAIRO_FORMAT_RGB24; - else - format = CAIRO_FORMAT_ARGB32; - - cairo_pixels = g_malloc (4 * width * height); - surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels, - format, - width, height, 4 * width); - cairo_surface_set_user_data (surface, &key, - cairo_pixels, (cairo_destroy_func_t)g_free); - - for (j = height; j; j--) - { - guchar *p = gdk_pixels; - guchar *q = cairo_pixels; - - if (n_channels == 3) - { - guchar *end = p + 3 * width; - - while (p < end) - { -#if G_BYTE_ORDER == GDK_LSB_FIRST - q[0] = p[2]; - q[1] = p[1]; - q[2] = p[2]; -#else - q[0] = p[0]; - q[1] = p[1]; - q[2] = p[2]; -#endif - p += 3; - q += 4; - } - } - else - { - guchar *end = p + 4 * width; - guint t1,t2,t3; - -#define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END - - while (p < end) - { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - MULT(q[0], p[2], p[3], t1); - MULT(q[1], p[1], p[3], t2); - MULT(q[2], p[0], p[3], t3); - q[3] = p[3]; -#else - q[0] = p[3]; - MULT(q[1], p[0], p[3], t1); - MULT(q[2], p[1], p[3], t2); - MULT(q[3], p[2], p[3], t3); -#endif - - p += 4; - q += 4; - } - -#undef MULT - } - - gdk_pixels += gdk_rowstride; - cairo_pixels += 4 * width; - } - - cairo_set_source_surface (cr, surface, pixbuf_x, pixbuf_y); -} - #define __GDK_PIXBUF_RENDER_C__ #include "gdkaliasdef.c" diff --git a/gdk/gdkpixbuf.h b/gdk/gdkpixbuf.h index aa5b4acba2..ed297135c7 100644 --- a/gdk/gdkpixbuf.h +++ b/gdk/gdkpixbuf.h @@ -80,11 +80,6 @@ GdkPixbuf *gdk_pixbuf_get_from_image (GdkPixbuf *dest, int width, int height); -void gdk_pixbuf_set_as_cairo_source (GdkPixbuf *pixbuf, - cairo_t *cr, - double pixbuf_x, - double pixbuf_y); - G_END_DECLS #endif /* __GDK_PIXBUF_H__ */ diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 87280a5052..85326aef65 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -1763,23 +1763,6 @@ gdk_window_set_bg_pattern (GdkWindow *window, } } -static void -region_path (cairo_t *cr, - GdkRegion *region) -{ - GdkRectangle *rectangles; - int n_rectangles, i; - - gdk_region_get_rectangles (region, &rectangles, &n_rectangles); - for (i = 0; i < n_rectangles; i++) - { - cairo_rectangle (cr, - rectangles[i].x, rectangles[i].y, - rectangles[i].width, rectangles[i].height); - } - g_free (rectangles); -} - static void gdk_window_clear_backing_rect (GdkWindow *window, gint x, @@ -1801,7 +1784,7 @@ gdk_window_clear_backing_rect (GdkWindow *window, cairo_rectangle (cr, x, y, width, height); cairo_clip (cr); - region_path (cr, paint->region); + gdk_cairo_region (cr, paint->region); cairo_fill (cr); cairo_destroy (cr); diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 52332318f8..2a069add48 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -402,11 +402,12 @@ gtk_button_set_use_underline #if IN_HEADER(__GTK_CALENDAR_H__) #if IN_FILE(__GTK_CALENDAR_C__) -gtk_calendar_clear_marks #ifndef GTK_DISABLE_DEPRECATED gtk_calendar_display_options -#endif gtk_calendar_freeze +gtk_calendar_thaw +#endif +gtk_calendar_clear_marks gtk_calendar_get_date gtk_calendar_get_display_options gtk_calendar_get_type G_GNUC_CONST @@ -415,7 +416,6 @@ gtk_calendar_new gtk_calendar_select_day gtk_calendar_select_month gtk_calendar_set_display_options -gtk_calendar_thaw gtk_calendar_unmark_day #endif #endif diff --git a/gtk/gtkcalendar.c b/gtk/gtkcalendar.c index 585fa85c4a..9c36354969 100644 --- a/gtk/gtkcalendar.c +++ b/gtk/gtkcalendar.c @@ -42,7 +42,10 @@ #include #include +#undef GTK_DISABLE_DEPRECATED #include "gtkcalendar.h" +#define GTK_DISABLE_DEPRECATED + #include "gtkdnd.h" #include "gtkintl.h" #include "gtkmain.h" @@ -234,12 +237,9 @@ enum PROP_LAST }; -static gint gtk_calendar_signals[LAST_SIGNAL] = { 0 }; - -static GtkWidgetClass *parent_class = NULL; +static guint gtk_calendar_signals[LAST_SIGNAL] = { 0 }; -typedef struct _GtkCalendarPrivateData GtkCalendarPrivateData; -struct _GtkCalendarPrivateData +struct _GtkCalendarPrivate { GdkWindow *header_win; GdkWindow *day_name_win; @@ -267,14 +267,7 @@ struct _GtkCalendarPrivateData guint max_label_char_descent; guint max_week_char_width; - guint freeze_count; - /* flags */ - guint dirty_header : 1; - guint dirty_day_names : 1; - guint dirty_main : 1; - guint dirty_week : 1; - guint year_before : 1; guint need_timer : 1; @@ -291,130 +284,94 @@ struct _GtkCalendarPrivateData gint drag_start_y; }; -#define GTK_CALENDAR_PRIVATE_DATA(widget) (((GtkCalendarPrivateData*)(GTK_CALENDAR (widget)->private_data))) - -typedef void (*GtkCalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data); - -static void gtk_calendar_class_init (GtkCalendarClass *class); -static void gtk_calendar_init (GtkCalendar *calendar); -static void gtk_calendar_finalize (GObject *calendar); -static void gtk_calendar_destroy (GtkObject *calendar); -static void gtk_calendar_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_calendar_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void gtk_calendar_realize (GtkWidget *widget); -static void gtk_calendar_unrealize (GtkWidget *widget); -static void gtk_calendar_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_calendar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gint gtk_calendar_expose (GtkWidget *widget, - GdkEventExpose *event); -static gint gtk_calendar_button_press (GtkWidget *widget, - GdkEventButton *event); -static gint gtk_calendar_button_release (GtkWidget *widget, - GdkEventButton *event); -static void gtk_calendar_main_button (GtkWidget *widget, - GdkEventButton *event); -static gint gtk_calendar_motion_notify (GtkWidget *widget, - GdkEventMotion *event); -static gint gtk_calendar_enter_notify (GtkWidget *widget, - GdkEventCrossing *event); -static gint gtk_calendar_leave_notify (GtkWidget *widget, - GdkEventCrossing *event); -static gint gtk_calendar_key_press (GtkWidget *widget, - GdkEventKey *event); -static gint gtk_calendar_scroll (GtkWidget *widget, - GdkEventScroll *event); -static void gtk_calendar_grab_notify (GtkWidget *widget, - gboolean was_grabbed); -static gboolean gtk_calendar_focus_out (GtkWidget *widget, - GdkEventFocus *event); -static void gtk_calendar_state_changed (GtkWidget *widget, - GtkStateType previous_state); -static void gtk_calendar_style_set (GtkWidget *widget, - GtkStyle *previous_style); -static void gtk_calendar_paint_header (GtkWidget *widget); -static void gtk_calendar_paint_day_names (GtkWidget *widget); -static void gtk_calendar_paint_week_numbers (GtkWidget *widget); -static void gtk_calendar_paint_main (GtkWidget *widget); - -static void gtk_calendar_select_and_focus_day (GtkCalendar *calendar, - guint day); - -static void gtk_calendar_paint_arrow (GtkWidget *widget, - guint arrow); -static void gtk_calendar_paint_day_num (GtkWidget *widget, - gint day); -static void gtk_calendar_paint_day (GtkWidget *widget, - gint row, - gint col); -static void gtk_calendar_compute_days (GtkCalendar *calendar); -static gint left_x_for_column (GtkCalendar *calendar, - gint column); -static gint top_y_for_row (GtkCalendar *calendar, - gint row); - -static void gtk_calendar_drag_data_get (GtkWidget *widget, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint time); -static void gtk_calendar_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time); -static gboolean gtk_calendar_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); -static void gtk_calendar_drag_leave (GtkWidget *widget, - GdkDragContext *context, - guint time); -static gboolean gtk_calendar_drag_drop (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); +#define GTK_CALENDAR_GET_PRIVATE(widget) (GTK_CALENDAR (widget)->priv) + +static void gtk_calendar_finalize (GObject *calendar); +static void gtk_calendar_destroy (GtkObject *calendar); +static void gtk_calendar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_calendar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void gtk_calendar_realize (GtkWidget *widget); +static void gtk_calendar_unrealize (GtkWidget *widget); +static void gtk_calendar_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_calendar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static gboolean gtk_calendar_expose (GtkWidget *widget, + GdkEventExpose *event); +static gboolean gtk_calendar_button_press (GtkWidget *widget, + GdkEventButton *event); +static gboolean gtk_calendar_button_release (GtkWidget *widget, + GdkEventButton *event); +static gboolean gtk_calendar_motion_notify (GtkWidget *widget, + GdkEventMotion *event); +static gboolean gtk_calendar_enter_notify (GtkWidget *widget, + GdkEventCrossing *event); +static gboolean gtk_calendar_leave_notify (GtkWidget *widget, + GdkEventCrossing *event); +static gboolean gtk_calendar_scroll (GtkWidget *widget, + GdkEventScroll *event); +static gboolean gtk_calendar_key_press (GtkWidget *widget, + GdkEventKey *event); +static gboolean gtk_calendar_focus_out (GtkWidget *widget, + GdkEventFocus *event); +static void gtk_calendar_grab_notify (GtkWidget *widget, + gboolean was_grabbed); +static void gtk_calendar_state_changed (GtkWidget *widget, + GtkStateType previous_state); +static void gtk_calendar_style_set (GtkWidget *widget, + GtkStyle *previous_style); + +static void gtk_calendar_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time); +static void gtk_calendar_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time); +static gboolean gtk_calendar_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static void gtk_calendar_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time); +static gboolean gtk_calendar_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); + +static void calendar_start_spinning (GtkCalendar *calendar, + gint click_child); +static void calendar_stop_spinning (GtkCalendar *calendar); + +static void calendar_invalidate_day (GtkCalendar *widget, + gint row, + gint col); +static void calendar_invalidate_day_num (GtkCalendar *widget, + gint day); +static void calendar_invalidate_arrow (GtkCalendar *widget, + guint arrow); + +static void calendar_compute_days (GtkCalendar *calendar); static char *default_abbreviated_dayname[7]; static char *default_monthname[12]; -GType -gtk_calendar_get_type (void) -{ - static GType calendar_type = 0; - - if (!calendar_type) - { - static const GTypeInfo calendar_info = - { - sizeof (GtkCalendarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gtk_calendar_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GtkCalendar), - 0, /* n_preallocs */ - (GInstanceInitFunc) gtk_calendar_init, - }; - - calendar_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkCalendar", - &calendar_info, 0); - } - - return calendar_type; -} +G_DEFINE_TYPE (GtkCalendar, gtk_calendar, GTK_TYPE_WIDGET) static void gtk_calendar_class_init (GtkCalendarClass *class) @@ -427,8 +384,6 @@ gtk_calendar_class_init (GtkCalendarClass *class) object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; - parent_class = g_type_class_peek_parent (class); - gobject_class->set_property = gtk_calendar_set_property; gobject_class->get_property = gtk_calendar_get_property; gobject_class->finalize = gtk_calendar_finalize; @@ -458,14 +413,6 @@ gtk_calendar_class_init (GtkCalendarClass *class) widget_class->drag_drop = gtk_calendar_drag_drop; widget_class->drag_data_received = gtk_calendar_drag_data_received; - class->month_changed = NULL; - class->day_selected = NULL; - class->day_selected_double_click = NULL; - class->prev_month = NULL; - class->next_month = NULL; - class->prev_year = NULL; - class->next_year = NULL; - g_object_class_install_property (gobject_class, PROP_YEAR, g_param_spec_int ("year", @@ -603,27 +550,29 @@ gtk_calendar_class_init (GtkCalendarClass *class) NULL, NULL, _gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); + + g_type_class_add_private (gobject_class, sizeof (GtkCalendarPrivate)); } static void gtk_calendar_init (GtkCalendar *calendar) { + GtkWidget *widget = GTK_WIDGET (calendar); time_t secs; struct tm *tm; gint i; char buffer[255]; time_t tmp_time; - GtkWidget *widget; - GtkCalendarPrivateData *private_data; + GtkCalendarPrivate *priv; gchar *year_before; gchar *week_start; - widget = GTK_WIDGET (calendar); + priv = calendar->priv = G_TYPE_INSTANCE_GET_PRIVATE (calendar, + GTK_TYPE_CALENDAR, + GtkCalendarPrivate); + GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); - calendar->private_data = g_malloc (sizeof (GtkCalendarPrivateData)); - private_data = GTK_CALENDAR_PRIVATE_DATA (calendar); - if (!default_abbreviated_dayname[0]) for (i=0; i<7; i++) { @@ -645,10 +594,11 @@ gtk_calendar_init (GtkCalendar *calendar) tm = localtime (&secs); calendar->month = tm->tm_mon; calendar->year = 1900 + tm->tm_year; - + + calendar_compute_days (calendar); + for (i=0;i<31;i++) calendar->marked_date[i] = FALSE; - calendar->num_marked_dates = 0; calendar->selected_day = tm->tm_mday; calendar->display_flags = ( GTK_CALENDAR_SHOW_HEADING | @@ -659,38 +609,30 @@ gtk_calendar_init (GtkCalendar *calendar) calendar->focus_row = -1; calendar->focus_col = -1; - calendar->xor_gc = NULL; - private_data->max_year_width = 0; - private_data->max_month_width = 0; - private_data->max_day_char_width = 0; - private_data->max_week_char_width = 0; + priv->max_year_width = 0; + priv->max_month_width = 0; + priv->max_day_char_width = 0; + priv->max_week_char_width = 0; - private_data->max_day_char_ascent = 0; - private_data->max_day_char_descent = 0; - private_data->max_label_char_ascent = 0; - private_data->max_label_char_descent = 0; + priv->max_day_char_ascent = 0; + priv->max_day_char_descent = 0; + priv->max_label_char_ascent = 0; + priv->max_label_char_descent = 0; - private_data->arrow_width = 10; + priv->arrow_width = 10; - private_data->freeze_count = 0; - - private_data->dirty_header = 0; - private_data->dirty_day_names = 0; - private_data->dirty_week = 0; - private_data->dirty_main = 0; - - private_data->need_timer = 0; - private_data->timer = 0; - private_data->click_child = -1; + priv->need_timer = 0; + priv->timer = 0; + priv->click_child = -1; - private_data->in_drag = 0; - private_data->drag_highlight = 0; + priv->in_drag = 0; + priv->drag_highlight = 0; gtk_drag_dest_set (widget, 0, NULL, 0, GDK_ACTION_COPY); gtk_drag_dest_add_text_targets (widget); - private_data->year_before = 0; + priv->year_before = 0; /* Translate to calendar:YM if you want years to be displayed * before months; otherwise translate to calendar:MY. @@ -703,13 +645,13 @@ gtk_calendar_init (GtkCalendar *calendar) */ year_before = _("calendar:MY"); if (strcmp (year_before, "calendar:YM") == 0) - private_data->year_before = 1; + priv->year_before = 1; else if (strcmp (year_before, "calendar:MY") != 0) g_warning ("Whoever translated calendar:MY did so wrongly.\n"); #ifdef HAVE__NL_TIME_FIRST_WEEKDAY week_start = nl_langinfo (_NL_TIME_FIRST_WEEKDAY); - private_data->week_start = *((unsigned char *) week_start) % 7; + priv->week_start = *((unsigned char *) week_start) % 7; #else /* Translate to calendar:week_start:0 if you want Sunday to be the * first day of the week to calendar:week_start:1 if you want Monday @@ -718,165 +660,25 @@ gtk_calendar_init (GtkCalendar *calendar) week_start = _("calendar:week_start:0"); if (strncmp (week_start, "calendar:week_start:", 20) == 0) - private_data->week_start = *(week_start + 20) - '0'; + priv->week_start = *(week_start + 20) - '0'; else - private_data->week_start = -1; + priv->week_start = -1; - if (private_data->week_start < 0 || private_data->week_start > 6) + if (priv->week_start < 0 || priv->week_start > 6) { g_warning ("Whoever translated calendar:week_start:0 did so wrongly.\n"); - private_data->week_start = 0; + priv->week_start = 0; } #endif } -GtkWidget* -gtk_calendar_new (void) -{ - return g_object_new (GTK_TYPE_CALENDAR, NULL); -} - -/* column_from_x: returns the column 0-6 that the - * x pixel of the xwindow is in */ -static gint -column_from_x (GtkCalendar *calendar, - gint event_x) -{ - gint c, column; - gint x_left, x_right; - - column = -1; - - for (c = 0; c < 7; c++) - { - x_left = left_x_for_column (calendar, c); - x_right = x_left + GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width; - - if (event_x >= x_left && event_x < x_right) - { - column = c; - break; - } - } - - return column; -} - -static gint -row_height (GtkCalendar *calendar) -{ - return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h - CALENDAR_MARGIN - - ((calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES) - ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6; -} - - -/* row_from_y: returns the row 0-5 that the - * y pixel of the xwindow is in */ -static gint -row_from_y (GtkCalendar *calendar, - gint event_y) -{ - gint r, row; - gint height; - gint y_top, y_bottom; - - height = row_height (calendar); - row = -1; - - for (r = 0; r < 6; r++) - { - y_top = top_y_for_row (calendar, r); - y_bottom = y_top + height; - - if (event_y >= y_top && event_y < y_bottom) - { - row = r; - break; - } - } - - return row; -}/* left_x_for_column: returns the x coordinate - * for the left of the column */ -static gint -left_x_for_column (GtkCalendar *calendar, - gint column) -{ - gint width; - gint x_left; - - if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL) - column = 6 - column; - - width = GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width; - if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) - x_left = CALENDAR_XSEP + (width + DAY_XSEP) * column; - else - x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column; - - return x_left; -} - -/* top_y_for_row: returns the y coordinate - * for the top of the row */ -static gint -top_y_for_row (GtkCalendar *calendar, - gint row) -{ - - return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h - - (CALENDAR_MARGIN + (6 - row) - * row_height (calendar))); -} - -static void -gtk_calendar_set_month_prev (GtkCalendar *calendar) -{ - gint month_len; - - if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE) - return; - - if (calendar->month == 0) - { - calendar->month = 11; - calendar->year--; - } - else - calendar->month--; - - month_len = month_length[leap (calendar->year)][calendar->month + 1]; - - gtk_calendar_freeze (calendar); - gtk_calendar_compute_days (calendar); - - g_signal_emit (calendar, - gtk_calendar_signals[PREV_MONTH_SIGNAL], - 0); - g_signal_emit (calendar, - gtk_calendar_signals[MONTH_CHANGED_SIGNAL], - 0); - - if (month_len < calendar->selected_day) - { - calendar->selected_day = 0; - gtk_calendar_select_day (calendar, month_len); - } - else - { - if (calendar->selected_day < 0) - calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1]; - gtk_calendar_select_day (calendar, calendar->selected_day); - } - - gtk_widget_queue_draw (GTK_WIDGET (calendar)); - gtk_calendar_thaw (calendar); -} - + +/**************************************** + * Utility Functions * + ****************************************/ static void -gtk_calendar_set_month_next (GtkCalendar *calendar) +calendar_set_month_next (GtkCalendar *calendar) { gint month_len; @@ -894,8 +696,7 @@ gtk_calendar_set_month_next (GtkCalendar *calendar) else calendar->month++; - gtk_calendar_freeze (calendar); - gtk_calendar_compute_days (calendar); + calendar_compute_days (calendar); g_signal_emit (calendar, gtk_calendar_signals[NEXT_MONTH_SIGNAL], 0); @@ -914,19 +715,17 @@ gtk_calendar_set_month_next (GtkCalendar *calendar) gtk_calendar_select_day (calendar, calendar->selected_day); gtk_widget_queue_draw (GTK_WIDGET (calendar)); - gtk_calendar_thaw (calendar); } static void -gtk_calendar_set_year_prev (GtkCalendar *calendar) +calendar_set_year_prev (GtkCalendar *calendar) { gint month_len; g_return_if_fail (GTK_IS_WIDGET (calendar)); calendar->year--; - gtk_calendar_freeze (calendar); - gtk_calendar_compute_days (calendar); + calendar_compute_days (calendar); g_signal_emit (calendar, gtk_calendar_signals[PREV_YEAR_SIGNAL], 0); @@ -945,11 +744,10 @@ gtk_calendar_set_year_prev (GtkCalendar *calendar) gtk_calendar_select_day (calendar, calendar->selected_day); gtk_widget_queue_draw (GTK_WIDGET (calendar)); - gtk_calendar_thaw (calendar); } static void -gtk_calendar_set_year_next (GtkCalendar *calendar) +calendar_set_year_next (GtkCalendar *calendar) { gint month_len; GtkWidget *widget; @@ -958,10 +756,8 @@ gtk_calendar_set_year_next (GtkCalendar *calendar) widget = GTK_WIDGET (calendar); - gtk_calendar_freeze (calendar); - calendar->year++; - gtk_calendar_compute_days (calendar); + calendar_compute_days (calendar); g_signal_emit (calendar, gtk_calendar_signals[NEXT_YEAR_SIGNAL], 0); @@ -980,609 +776,920 @@ gtk_calendar_set_year_next (GtkCalendar *calendar) gtk_calendar_select_day (calendar, calendar->selected_day); gtk_widget_queue_draw (GTK_WIDGET (calendar)); - gtk_calendar_thaw (calendar); } static void -gtk_calendar_main_button (GtkWidget *widget, - GdkEventButton *event) +calendar_compute_days (GtkCalendar *calendar) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - gint x, y; - gint row, col; - gint day_month; + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (GTK_WIDGET (calendar)); + gint month; + gint year; + gint ndays_in_month; + gint ndays_in_prev_month; + gint first_day; + gint row; + gint col; gint day; + + g_return_if_fail (GTK_IS_CALENDAR (calendar)); + + year = calendar->year; + month = calendar->month + 1; - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); + ndays_in_month = month_length[leap (year)][month]; - x = (gint) (event->x); - y = (gint) (event->y); + first_day = day_of_week (year, month, 1); + first_day = (first_day + 7 - priv->week_start) % 7; - row = row_from_y (calendar, y); - col = column_from_x (calendar, x); - - /* If row or column isn't found, just return. */ - if (row == -1 || col == -1) - return; + /* Compute days of previous month */ + if (month > 1) + ndays_in_prev_month = month_length[leap (year)][month-1]; + else + ndays_in_prev_month = month_length[leap (year)][12]; + day = ndays_in_prev_month - first_day + 1; - day_month = calendar->day_month[row][col]; - - if (event->type == GDK_BUTTON_PRESS) + row = 0; + if (first_day > 0) { - day = calendar->day[row][col]; - - if (day_month == MONTH_PREV) - gtk_calendar_set_month_prev (calendar); - else if (day_month == MONTH_NEXT) - gtk_calendar_set_month_next (calendar); + for (col = 0; col < first_day; col++) + { + calendar->day[row][col] = day; + calendar->day_month[row][col] = MONTH_PREV; + day++; + } + } + + /* Compute days of current month */ + col = first_day; + for (day = 1; day <= ndays_in_month; day++) + { + calendar->day[row][col] = day; + calendar->day_month[row][col] = MONTH_CURRENT; - if (!GTK_WIDGET_HAS_FOCUS (widget)) - gtk_widget_grab_focus (widget); - - if (event->button == 1) + col++; + if (col == 7) { - private_data->in_drag = 1; - private_data->drag_start_x = x; - private_data->drag_start_y = y; + row++; + col = 0; } - - gtk_calendar_select_and_focus_day (calendar, day); } - else if (event->type == GDK_2BUTTON_PRESS) + + /* Compute days of next month */ + day = 1; + for (; row <= 5; row++) { - private_data->in_drag = 0; - if (day_month == MONTH_CURRENT) - g_signal_emit (calendar, - gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL], - 0); + for (; col <= 6; col++) + { + calendar->day[row][col] = day; + calendar->day_month[row][col] = MONTH_NEXT; + day++; + } + col = 0; } } static void -gtk_calendar_realize_arrows (GtkWidget *widget) +calendar_select_and_focus_day (GtkCalendar *calendar, + guint day) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - GdkWindowAttr attributes; - gint attributes_mask; - gint i; - gboolean year_left; + gint old_focus_row = calendar->focus_row; + gint old_focus_col = calendar->focus_col; + gint row; + gint col; - g_return_if_fail (GTK_IS_CALENDAR (widget)); + for (row = 0; row < 6; row ++) + for (col = 0; col < 7; col++) + { + if (calendar->day_month[row][col] == MONTH_CURRENT + && calendar->day[row][col] == day) + { + calendar->focus_row = row; + calendar->focus_col = col; + } + } + + if (old_focus_row != -1 && old_focus_col != -1) + calendar_invalidate_day (calendar, old_focus_row, old_focus_col); - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); + gtk_calendar_select_day (calendar, day); +} - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - year_left = private_data->year_before; - else - year_left = !private_data->year_before; - - /* Arrow windows ------------------------------------- */ - if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE) - && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)) - { - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - attributes.y = 3; - attributes.width = private_data->arrow_width; - attributes.height = private_data->header_h - 7; - for (i = 0; i < 4; i++) - { - switch (i) - { - case ARROW_MONTH_LEFT: - if (year_left) - attributes.x = (widget->allocation.width - 2 * widget->style->xthickness - - (3 + 2*private_data->arrow_width - + private_data->max_month_width)); - else - attributes.x = 3; - break; - case ARROW_MONTH_RIGHT: - if (year_left) - attributes.x = (widget->allocation.width - 2 * widget->style->xthickness - - 3 - private_data->arrow_width); - else - attributes.x = (private_data->arrow_width - + private_data->max_month_width); - break; - case ARROW_YEAR_LEFT: - if (year_left) - attributes.x = 3; - else - attributes.x = (widget->allocation.width - 2 * widget->style->xthickness - - (3 + 2*private_data->arrow_width - + private_data->max_year_width)); - break; - case ARROW_YEAR_RIGHT: - if (year_left) - attributes.x = (private_data->arrow_width - + private_data->max_year_width); - else - attributes.x = (widget->allocation.width - 2 * widget->style->xthickness - - 3 - private_data->arrow_width); - break; - } - private_data->arrow_win[i] = gdk_window_new (private_data->header_win, - &attributes, - attributes_mask); - if (GTK_WIDGET_IS_SENSITIVE (widget)) - private_data->arrow_state[i] = GTK_STATE_NORMAL; - else - private_data->arrow_state[i] = GTK_STATE_INSENSITIVE; - gdk_window_set_background (private_data->arrow_win[i], - HEADER_BG_COLOR (GTK_WIDGET (calendar))); - gdk_window_show (private_data->arrow_win[i]); - gdk_window_set_user_data (private_data->arrow_win[i], widget); - } - } - else - { - for (i = 0; i < 4; i++) - private_data->arrow_win[i] = NULL; - } + +/**************************************** + * Layout computation utilities * + ****************************************/ + +static gint +calendar_row_height (GtkCalendar *calendar) +{ + return (GTK_CALENDAR_GET_PRIVATE (calendar)->main_h - CALENDAR_MARGIN + - ((calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES) + ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6; } -static void -gtk_calendar_realize_header (GtkWidget *widget) + +/* calendar_left_x_for_column: returns the x coordinate + * for the left of the column */ +static gint +calendar_left_x_for_column (GtkCalendar *calendar, + gint column) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - GdkWindowAttr attributes; - gint attributes_mask; + gint width; + gint x_left; - g_return_if_fail (GTK_IS_CALENDAR (widget)); + if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL) + column = 6 - column; + + width = GTK_CALENDAR_GET_PRIVATE (calendar)->day_width; + if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) + x_left = CALENDAR_XSEP + (width + DAY_XSEP) * column; + else + x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column; - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); + return x_left; +} - /* Header window ------------------------------------- */ - if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING) +/* column_from_x: returns the column 0-6 that the + * x pixel of the xwindow is in */ +static gint +calendar_column_from_x (GtkCalendar *calendar, + gint event_x) +{ + gint c, column; + gint x_left, x_right; + + column = -1; + + for (c = 0; c < 7; c++) { - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - attributes.x = widget->style->xthickness; - attributes.y = widget->style->ythickness; - attributes.width = widget->allocation.width - 2 * attributes.x; - attributes.height = private_data->header_h - 2 * attributes.y; - private_data->header_win = gdk_window_new (widget->window, - &attributes, attributes_mask); - - gdk_window_set_background (private_data->header_win, - HEADER_BG_COLOR (GTK_WIDGET (calendar))); - gdk_window_show (private_data->header_win); - gdk_window_set_user_data (private_data->header_win, widget); + x_left = calendar_left_x_for_column (calendar, c); + x_right = x_left + GTK_CALENDAR_GET_PRIVATE (calendar)->day_width; + if (event_x >= x_left && event_x < x_right) + { + column = c; + break; + } } - else - { - private_data->header_win = NULL; - } - gtk_calendar_realize_arrows (widget); + + return column; } -static void -gtk_calendar_realize_day_names (GtkWidget *widget) +/* calendar_top_y_for_row: returns the y coordinate + * for the top of the row */ +static gint +calendar_top_y_for_row (GtkCalendar *calendar, + gint row) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - GdkWindowAttr attributes; - gint attributes_mask; - g_return_if_fail (GTK_IS_CALENDAR (widget)); - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); + return (GTK_CALENDAR_GET_PRIVATE (calendar)->main_h + - (CALENDAR_MARGIN + (6 - row) + * calendar_row_height (calendar))); +} - /* Day names window --------------------------------- */ - if ( calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES) - { - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - attributes.x = (widget->style->xthickness + INNER_BORDER); - attributes.y = private_data->header_h + (widget->style->ythickness - + INNER_BORDER); - attributes.width = (widget->allocation.width - - (widget->style->xthickness + INNER_BORDER) - * 2); - attributes.height = private_data->day_name_h; - private_data->day_name_win = gdk_window_new (widget->window, - &attributes, - attributes_mask); - gdk_window_set_background (private_data->day_name_win, - BACKGROUND_COLOR ( GTK_WIDGET ( calendar))); - gdk_window_show (private_data->day_name_win); - gdk_window_set_user_data (private_data->day_name_win, widget); - } - else +/* row_from_y: returns the row 0-5 that the + * y pixel of the xwindow is in */ +static gint +calendar_row_from_y (GtkCalendar *calendar, + gint event_y) +{ + gint r, row; + gint height; + gint y_top, y_bottom; + + height = calendar_row_height (calendar); + row = -1; + + for (r = 0; r < 6; r++) { - private_data->day_name_win = NULL; + y_top = calendar_top_y_for_row (calendar, r); + y_bottom = y_top + height; + + if (event_y >= y_top && event_y < y_bottom) + { + row = r; + break; + } } + + return row; } static void -gtk_calendar_realize_week_numbers (GtkWidget *widget) +calendar_arrow_rectangle (GtkCalendar *calendar, + guint arrow, + GdkRectangle *rect) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - GdkWindowAttr attributes; - gint attributes_mask; - - g_return_if_fail (GTK_IS_CALENDAR (widget)); - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + gboolean year_left; - /* Week number window -------------------------------- */ - if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) - { - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - attributes.x = widget->style->xthickness + INNER_BORDER; - attributes.y = (private_data->header_h + private_data->day_name_h - + (widget->style->ythickness + INNER_BORDER)); - attributes.width = private_data->week_width; - attributes.height = private_data->main_h; - private_data->week_win = gdk_window_new (widget->window, - &attributes, attributes_mask); - gdk_window_set_background (private_data->week_win, - BACKGROUND_COLOR (GTK_WIDGET (calendar))); - gdk_window_show (private_data->week_win); - gdk_window_set_user_data (private_data->week_win, widget); - } + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + year_left = priv->year_before; else + year_left = !priv->year_before; + + rect->y = 3; + rect->width = priv->arrow_width; + rect->height = priv->header_h - 7; + + switch (arrow) { - private_data->week_win = NULL; + case ARROW_MONTH_LEFT: + if (year_left) + rect->x = (widget->allocation.width - 2 * widget->style->xthickness + - (3 + 2*priv->arrow_width + + priv->max_month_width)); + else + rect->x = 3; + break; + case ARROW_MONTH_RIGHT: + if (year_left) + rect->x = (widget->allocation.width - 2 * widget->style->xthickness + - 3 - priv->arrow_width); + else + rect->x = (priv->arrow_width + + priv->max_month_width); + break; + case ARROW_YEAR_LEFT: + if (year_left) + rect->x = 3; + else + rect->x = (widget->allocation.width - 2 * widget->style->xthickness + - (3 + 2*priv->arrow_width + + priv->max_year_width)); + break; + case ARROW_YEAR_RIGHT: + if (year_left) + rect->x = (priv->arrow_width + + priv->max_year_width); + else + rect->x = (widget->allocation.width - 2 * widget->style->xthickness + - 3 - priv->arrow_width); + break; } } static void -gtk_calendar_realize (GtkWidget *widget) +calendar_day_rectangle (GtkCalendar *calendar, + gint row, + gint col, + GdkRectangle *rect) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - GdkWindowAttr attributes; - gint attributes_mask; - GdkGCValues values; - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - gtk_calendar_compute_days (calendar); - - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.event_mask = (gtk_widget_get_events (widget) - | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK | GDK_SCROLL_MASK); - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - widget->window = gdk_window_new (widget->parent->window, - &attributes, attributes_mask); - - widget->style = gtk_style_attach (widget->style, widget->window); - - /* Header window ------------------------------------- */ - gtk_calendar_realize_header (widget); - /* Day names window --------------------------------- */ - gtk_calendar_realize_day_names (widget); - /* Week number window -------------------------------- */ - gtk_calendar_realize_week_numbers (widget); - /* Main Window -------------------------------------- */ - attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); - - attributes.x = private_data->week_width + (widget->style->ythickness + INNER_BORDER); - attributes.y = (private_data->header_h + private_data->day_name_h - + (widget->style->ythickness + INNER_BORDER)); - attributes.width = (widget->allocation.width - attributes.x - - (widget->style->xthickness + INNER_BORDER)); - attributes.height = private_data->main_h; - private_data->main_win = gdk_window_new (widget->window, - &attributes, attributes_mask); - gdk_window_set_background (private_data->main_win, - BACKGROUND_COLOR ( GTK_WIDGET ( calendar))); - gdk_window_show (private_data->main_win); - gdk_window_set_user_data (private_data->main_win, widget); - gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget)); - gdk_window_show (widget->window); - gdk_window_set_user_data (widget->window, widget); - - /* Set widgets gc */ - calendar->gc = gdk_gc_new (widget->window); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); - values.foreground = widget->style->white; - values.function = GDK_XOR; - calendar->xor_gc = gdk_gc_new_with_values (widget->window, - &values, - GDK_GC_FOREGROUND | - GDK_GC_FUNCTION); + rect->x = calendar_left_x_for_column (calendar, col); + rect->y = calendar_top_y_for_row (calendar, row); + rect->height = calendar_row_height (calendar); + rect->width = priv->day_width; } static void -gtk_calendar_unrealize (GtkWidget *widget) +calendar_set_month_prev (GtkCalendar *calendar) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - gint i; + gint month_len; - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); + if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE) + return; - if (private_data->header_win) + if (calendar->month == 0) { - for (i = 0; i < 4; i++) - { - if (private_data->arrow_win[i]) - { - gdk_window_set_user_data (private_data->arrow_win[i], NULL); - gdk_window_destroy (private_data->arrow_win[i]); - private_data->arrow_win[i] = NULL; - } - } - gdk_window_set_user_data (private_data->header_win, NULL); - gdk_window_destroy (private_data->header_win); - private_data->header_win = NULL; - } + calendar->month = 11; + calendar->year--; + } + else + calendar->month--; - if (private_data->week_win) - { - gdk_window_set_user_data (private_data->week_win, NULL); - gdk_window_destroy (private_data->week_win); - private_data->week_win = NULL; - } + month_len = month_length[leap (calendar->year)][calendar->month + 1]; + + calendar_compute_days (calendar); + + g_signal_emit (calendar, + gtk_calendar_signals[PREV_MONTH_SIGNAL], + 0); + g_signal_emit (calendar, + gtk_calendar_signals[MONTH_CHANGED_SIGNAL], + 0); - if (private_data->main_win) + if (month_len < calendar->selected_day) { - gdk_window_set_user_data (private_data->main_win, NULL); - gdk_window_destroy (private_data->main_win); - private_data->main_win = NULL; + calendar->selected_day = 0; + gtk_calendar_select_day (calendar, month_len); } - if (private_data->day_name_win) + else { - gdk_window_set_user_data (private_data->day_name_win, NULL); - gdk_window_destroy (private_data->day_name_win); - private_data->day_name_win = NULL; + if (calendar->selected_day < 0) + calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1]; + gtk_calendar_select_day (calendar, calendar->selected_day); } - if (calendar->xor_gc) - g_object_unref (calendar->xor_gc); - if (calendar->gc) - g_object_unref (calendar->gc); - - if (GTK_WIDGET_CLASS (parent_class)->unrealize) - (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); + + gtk_widget_queue_draw (GTK_WIDGET (calendar)); } + +/**************************************** + * Basic object methods * + ****************************************/ + static void -gtk_calendar_size_request (GtkWidget *widget, - GtkRequisition *requisition) +gtk_calendar_finalize (GObject *object) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - PangoLayout *layout; - PangoRectangle logical_rect; + (* G_OBJECT_CLASS (gtk_calendar_parent_class)->finalize) (object); +} - gint height; - gint i; - gchar buffer[255]; - gint calendar_margin = CALENDAR_MARGIN; - gint header_width, main_width; - gint max_header_height = 0; - gint focus_width; - gint focus_padding; +static void +gtk_calendar_destroy (GtkObject *object) +{ + calendar_stop_spinning (GTK_CALENDAR (object)); - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - gtk_widget_style_get (GTK_WIDGET (widget), - "focus-line-width", &focus_width, - "focus-padding", &focus_padding, - NULL); + GTK_OBJECT_CLASS (gtk_calendar_parent_class)->destroy (object); +} - layout = gtk_widget_create_pango_layout (widget, NULL); - - /* - * Calculate the requisition width for the widget. - */ - - /* Header width */ + +static void +calendar_set_display_option (GtkCalendar *calendar, + GtkCalendarDisplayOptions flag, + gboolean setting) +{ + GtkCalendarDisplayOptions flags; + if (setting) + flags = calendar->display_flags | flag; + else + flags = calendar->display_flags & ~flag; + gtk_calendar_display_options (calendar, flags); +} + +static gboolean +calendar_get_display_option (GtkCalendar *calendar, + GtkCalendarDisplayOptions flag) +{ + return (calendar->display_flags & flag) != 0; +} + +static void +gtk_calendar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkCalendar *calendar; + + calendar = GTK_CALENDAR (object); + + switch (prop_id) + { + case PROP_YEAR: + gtk_calendar_select_month (calendar, + calendar->month, + g_value_get_int (value)); + break; + case PROP_MONTH: + gtk_calendar_select_month (calendar, + g_value_get_int (value), + calendar->year); + break; + case PROP_DAY: + gtk_calendar_select_day (calendar, + g_value_get_int (value)); + break; + case PROP_SHOW_HEADING: + calendar_set_display_option (calendar, + GTK_CALENDAR_SHOW_HEADING, + g_value_get_boolean (value)); + break; + case PROP_SHOW_DAY_NAMES: + calendar_set_display_option (calendar, + GTK_CALENDAR_SHOW_DAY_NAMES, + g_value_get_boolean (value)); + break; + case PROP_NO_MONTH_CHANGE: + calendar_set_display_option (calendar, + GTK_CALENDAR_NO_MONTH_CHANGE, + g_value_get_boolean (value)); + break; + case PROP_SHOW_WEEK_NUMBERS: + calendar_set_display_option (calendar, + GTK_CALENDAR_SHOW_WEEK_NUMBERS, + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gtk_calendar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkCalendar *calendar; + + calendar = GTK_CALENDAR (object); + + switch (prop_id) + { + case PROP_YEAR: + g_value_set_int (value, calendar->year); + break; + case PROP_MONTH: + g_value_set_int (value, calendar->month); + break; + case PROP_DAY: + g_value_set_int (value, calendar->selected_day); + break; + case PROP_SHOW_HEADING: + g_value_set_boolean (value, calendar_get_display_option (calendar, + GTK_CALENDAR_SHOW_HEADING)); + break; + case PROP_SHOW_DAY_NAMES: + g_value_set_boolean (value, calendar_get_display_option (calendar, + GTK_CALENDAR_SHOW_DAY_NAMES)); + break; + case PROP_NO_MONTH_CHANGE: + g_value_set_boolean (value, calendar_get_display_option (calendar, + GTK_CALENDAR_NO_MONTH_CHANGE)); + break; + case PROP_SHOW_WEEK_NUMBERS: + g_value_set_boolean (value, calendar_get_display_option (calendar, + GTK_CALENDAR_SHOW_WEEK_NUMBERS)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +/**************************************** + * Realization * + ****************************************/ + +static void +calendar_realize_arrows (GtkCalendar *calendar) +{ + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + GdkWindowAttr attributes; + gint attributes_mask; + gint i; - if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING) + /* Arrow windows ------------------------------------- */ + if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE) + && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)) { - private_data->max_month_width = 0; - for (i = 0; i < 12; i++) - { - pango_layout_set_text (layout, default_monthname[i], -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - private_data->max_month_width = MAX (private_data->max_month_width, - logical_rect.width + 8); - max_header_height = MAX (max_header_height, logical_rect.height); - } - private_data->max_year_width = 0; - for (i=0; i<10; i++) + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + for (i = 0; i < 4; i++) { - g_snprintf (buffer, sizeof (buffer), "%d%d%d%d", i,i,i,i); - pango_layout_set_text (layout, buffer, -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - private_data->max_year_width = MAX (private_data->max_year_width, - logical_rect.width + 8); - max_header_height = MAX (max_header_height, logical_rect.height); + GdkRectangle rect; + calendar_arrow_rectangle (calendar, i, &rect); + + attributes.x = rect.x; + attributes.y = rect.y; + attributes.width = rect.width; + attributes.height = rect.width; + priv->arrow_win[i] = gdk_window_new (priv->header_win, + &attributes, + attributes_mask); + if (GTK_WIDGET_IS_SENSITIVE (widget)) + priv->arrow_state[i] = GTK_STATE_NORMAL; + else + priv->arrow_state[i] = GTK_STATE_INSENSITIVE; + gdk_window_set_background (priv->arrow_win[i], + HEADER_BG_COLOR (GTK_WIDGET (calendar))); + gdk_window_show (priv->arrow_win[i]); + gdk_window_set_user_data (priv->arrow_win[i], widget); } - } - else - { - private_data->max_month_width = 0; - private_data->max_year_width = 0; } - - if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE) - header_width = (private_data->max_month_width - + private_data->max_year_width - + 3 * 3); else - header_width = (private_data->max_month_width - + private_data->max_year_width - + 4 * private_data->arrow_width + 3 * 3); - - /* Mainwindow labels width */ - - private_data->max_day_char_width = 0; - private_data->min_day_width = 0; - private_data->max_label_char_ascent = 0; - private_data->max_label_char_descent = 0; - - for (i = 0; i < 9; i++) { - g_snprintf (buffer, sizeof (buffer), "%d%d", i, i); - pango_layout_set_text (layout, buffer, -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - private_data->min_day_width = MAX (private_data->min_day_width, - logical_rect.width); - - private_data->max_day_char_ascent = MAX (private_data->max_label_char_ascent, - PANGO_ASCENT (logical_rect)); - private_data->max_day_char_descent = MAX (private_data->max_label_char_descent, - PANGO_DESCENT (logical_rect)); + for (i = 0; i < 4; i++) + priv->arrow_win[i] = NULL; } - /* We add one to max_day_char_width to be able to make the marked day "bold" */ - private_data->max_day_char_width = private_data->min_day_width / 2 + 1; - - if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES) - for (i = 0; i < 7; i++) - { - pango_layout_set_text (layout, default_abbreviated_dayname[i], -1); - pango_layout_line_get_pixel_extents (pango_layout_get_lines (layout)->data, NULL, &logical_rect); +} - private_data->min_day_width = MAX (private_data->min_day_width, logical_rect.width); - private_data->max_label_char_ascent = MAX (private_data->max_label_char_ascent, - PANGO_ASCENT (logical_rect)); - private_data->max_label_char_descent = MAX (private_data->max_label_char_descent, - PANGO_DESCENT (logical_rect)); - } - - private_data->max_week_char_width = 0; - if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) - for (i = 0; i < 9; i++) - { - g_snprintf (buffer, sizeof (buffer), "%d%d", i, i); - pango_layout_set_text (layout, buffer, -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - private_data->max_week_char_width = MAX (private_data->max_week_char_width, - logical_rect.width / 2); - } - - main_width = (7 * (private_data->min_day_width + (focus_padding + focus_width) * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2 - + (private_data->max_week_char_width - ? private_data->max_week_char_width * 2 + (focus_padding + focus_width) * 2 + CALENDAR_XSEP * 2 - : 0)); - - - requisition->width = MAX (header_width, main_width + INNER_BORDER * 2) + widget->style->xthickness * 2; - - /* - * Calculate the requisition height for the widget. - */ +static void +calendar_realize_header (GtkCalendar *calendar) +{ + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + GdkWindowAttr attributes; + gint attributes_mask; + /* Header window ------------------------------------- */ if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING) { - private_data->header_h = (max_header_height + CALENDAR_YSEP * 2); + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + attributes.x = widget->style->xthickness; + attributes.y = widget->style->ythickness; + attributes.width = widget->allocation.width - 2 * attributes.x; + attributes.height = priv->header_h - 2 * attributes.y; + priv->header_win = gdk_window_new (widget->window, + &attributes, attributes_mask); + + gdk_window_set_background (priv->header_win, + HEADER_BG_COLOR (GTK_WIDGET (calendar))); + gdk_window_show (priv->header_win); + gdk_window_set_user_data (priv->header_win, widget); + } else { - private_data->header_h = 0; + priv->header_win = NULL; } + calendar_realize_arrows (calendar); +} + +static void +calendar_realize_day_names (GtkCalendar *calendar) +{ + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + GdkWindowAttr attributes; + gint attributes_mask; - if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES) + /* Day names window --------------------------------- */ + if ( calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES) { - private_data->day_name_h = (private_data->max_label_char_ascent - + private_data->max_label_char_descent - + 2 * (focus_padding + focus_width) + calendar_margin); - calendar_margin = CALENDAR_YSEP; - } + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + attributes.x = (widget->style->xthickness + INNER_BORDER); + attributes.y = priv->header_h + (widget->style->ythickness + + INNER_BORDER); + attributes.width = (widget->allocation.width + - (widget->style->xthickness + INNER_BORDER) + * 2); + attributes.height = priv->day_name_h; + priv->day_name_win = gdk_window_new (widget->window, + &attributes, + attributes_mask); + gdk_window_set_background (priv->day_name_win, + BACKGROUND_COLOR ( GTK_WIDGET ( calendar))); + gdk_window_show (priv->day_name_win); + gdk_window_set_user_data (priv->day_name_win, widget); + } else { - private_data->day_name_h = 0; + priv->day_name_win = NULL; } - - private_data->main_h = (CALENDAR_MARGIN + calendar_margin - + 6 * (private_data->max_day_char_ascent - + private_data->max_day_char_descent - + 2 * (focus_padding + focus_width)) - + DAY_YSEP * 5); - - height = (private_data->header_h + private_data->day_name_h - + private_data->main_h); - - requisition->height = height + (widget->style->ythickness + INNER_BORDER) * 2; - - g_object_unref (layout); } static void -gtk_calendar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +calendar_realize_week_numbers (GtkCalendar *calendar) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - gint xthickness = widget->style->xthickness; - gint ythickness = widget->style->xthickness; - gboolean year_left; - - widget->allocation = *allocation; + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + GdkWindowAttr attributes; + gint attributes_mask; - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); + /* Week number window -------------------------------- */ + if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) + { + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + attributes.x = widget->style->xthickness + INNER_BORDER; + attributes.y = (priv->header_h + priv->day_name_h + + (widget->style->ythickness + INNER_BORDER)); + attributes.width = priv->week_width; + attributes.height = priv->main_h; + priv->week_win = gdk_window_new (widget->window, + &attributes, attributes_mask); + gdk_window_set_background (priv->week_win, + BACKGROUND_COLOR (GTK_WIDGET (calendar))); + gdk_window_show (priv->week_win); + gdk_window_set_user_data (priv->week_win, widget); + } + else + { + priv->week_win = NULL; + } +} + +static void +gtk_calendar_realize (GtkWidget *widget) +{ + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + GdkWindowAttr attributes; + gint attributes_mask; + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = (gtk_widget_get_events (widget) + | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK | GDK_SCROLL_MASK); + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + widget->window = gdk_window_new (widget->parent->window, + &attributes, attributes_mask); + + widget->style = gtk_style_attach (widget->style, widget->window); + + /* Header window ------------------------------------- */ + calendar_realize_header (calendar); + /* Day names window --------------------------------- */ + calendar_realize_day_names (calendar); + /* Week number window -------------------------------- */ + calendar_realize_week_numbers (calendar); + /* Main Window -------------------------------------- */ + attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); + + attributes.x = priv->week_width + (widget->style->ythickness + INNER_BORDER); + attributes.y = (priv->header_h + priv->day_name_h + + (widget->style->ythickness + INNER_BORDER)); + attributes.width = (widget->allocation.width - attributes.x + - (widget->style->xthickness + INNER_BORDER)); + attributes.height = priv->main_h; + priv->main_win = gdk_window_new (widget->window, + &attributes, attributes_mask); + gdk_window_set_background (priv->main_win, + BACKGROUND_COLOR ( GTK_WIDGET ( calendar))); + gdk_window_show (priv->main_win); + gdk_window_set_user_data (priv->main_win, widget); + gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget)); + gdk_window_show (widget->window); + gdk_window_set_user_data (widget->window, widget); +} + +static void +gtk_calendar_unrealize (GtkWidget *widget) +{ + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + gint i; + + if (priv->header_win) + { + for (i = 0; i < 4; i++) + { + if (priv->arrow_win[i]) + { + gdk_window_set_user_data (priv->arrow_win[i], NULL); + gdk_window_destroy (priv->arrow_win[i]); + priv->arrow_win[i] = NULL; + } + } + gdk_window_set_user_data (priv->header_win, NULL); + gdk_window_destroy (priv->header_win); + priv->header_win = NULL; + } + + if (priv->week_win) + { + gdk_window_set_user_data (priv->week_win, NULL); + gdk_window_destroy (priv->week_win); + priv->week_win = NULL; + } + + if (priv->main_win) + { + gdk_window_set_user_data (priv->main_win, NULL); + gdk_window_destroy (priv->main_win); + priv->main_win = NULL; + } + if (priv->day_name_win) + { + gdk_window_set_user_data (priv->day_name_win, NULL); + gdk_window_destroy (priv->day_name_win); + priv->day_name_win = NULL; + } + + if (GTK_WIDGET_CLASS (gtk_calendar_parent_class)->unrealize) + (* GTK_WIDGET_CLASS (gtk_calendar_parent_class)->unrealize) (widget); +} + + +/**************************************** + * Size Request and Allocate * + ****************************************/ + +static void +gtk_calendar_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + PangoLayout *layout; + PangoRectangle logical_rect; + + gint height; + gint i; + gchar buffer[255]; + gint calendar_margin = CALENDAR_MARGIN; + gint header_width, main_width; + gint max_header_height = 0; + gint focus_width; + gint focus_padding; + + gtk_widget_style_get (GTK_WIDGET (widget), + "focus-line-width", &focus_width, + "focus-padding", &focus_padding, + NULL); + + layout = gtk_widget_create_pango_layout (widget, NULL); + + /* + * Calculate the requisition width for the widget. + */ + + /* Header width */ + + if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING) + { + priv->max_month_width = 0; + for (i = 0; i < 12; i++) + { + pango_layout_set_text (layout, default_monthname[i], -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + priv->max_month_width = MAX (priv->max_month_width, + logical_rect.width + 8); + max_header_height = MAX (max_header_height, logical_rect.height); + } + priv->max_year_width = 0; + for (i=0; i<10; i++) + { + g_snprintf (buffer, sizeof (buffer), "%d%d%d%d", i,i,i,i); + pango_layout_set_text (layout, buffer, -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + priv->max_year_width = MAX (priv->max_year_width, + logical_rect.width + 8); + max_header_height = MAX (max_header_height, logical_rect.height); + } + } + else + { + priv->max_month_width = 0; + priv->max_year_width = 0; + } + + if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE) + header_width = (priv->max_month_width + + priv->max_year_width + + 3 * 3); + else + header_width = (priv->max_month_width + + priv->max_year_width + + 4 * priv->arrow_width + 3 * 3); + + /* Mainwindow labels width */ + + priv->max_day_char_width = 0; + priv->min_day_width = 0; + priv->max_label_char_ascent = 0; + priv->max_label_char_descent = 0; + + for (i = 0; i < 9; i++) + { + g_snprintf (buffer, sizeof (buffer), "%d%d", i, i); + pango_layout_set_text (layout, buffer, -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + priv->min_day_width = MAX (priv->min_day_width, + logical_rect.width); + + priv->max_day_char_ascent = MAX (priv->max_label_char_ascent, + PANGO_ASCENT (logical_rect)); + priv->max_day_char_descent = MAX (priv->max_label_char_descent, + PANGO_DESCENT (logical_rect)); + } + /* We add one to max_day_char_width to be able to make the marked day "bold" */ + priv->max_day_char_width = priv->min_day_width / 2 + 1; + + if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES) + for (i = 0; i < 7; i++) + { + pango_layout_set_text (layout, default_abbreviated_dayname[i], -1); + pango_layout_line_get_pixel_extents (pango_layout_get_lines (layout)->data, NULL, &logical_rect); + + priv->min_day_width = MAX (priv->min_day_width, logical_rect.width); + priv->max_label_char_ascent = MAX (priv->max_label_char_ascent, + PANGO_ASCENT (logical_rect)); + priv->max_label_char_descent = MAX (priv->max_label_char_descent, + PANGO_DESCENT (logical_rect)); + } + + priv->max_week_char_width = 0; + if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) + for (i = 0; i < 9; i++) + { + g_snprintf (buffer, sizeof (buffer), "%d%d", i, i); + pango_layout_set_text (layout, buffer, -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + priv->max_week_char_width = MAX (priv->max_week_char_width, + logical_rect.width / 2); + } + + main_width = (7 * (priv->min_day_width + (focus_padding + focus_width) * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2 + + (priv->max_week_char_width + ? priv->max_week_char_width * 2 + (focus_padding + focus_width) * 2 + CALENDAR_XSEP * 2 + : 0)); + + + requisition->width = MAX (header_width, main_width + INNER_BORDER * 2) + widget->style->xthickness * 2; + + /* + * Calculate the requisition height for the widget. + */ + + if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING) + { + priv->header_h = (max_header_height + CALENDAR_YSEP * 2); + } + else + { + priv->header_h = 0; + } + + if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES) + { + priv->day_name_h = (priv->max_label_char_ascent + + priv->max_label_char_descent + + 2 * (focus_padding + focus_width) + calendar_margin); + calendar_margin = CALENDAR_YSEP; + } + else + { + priv->day_name_h = 0; + } + + priv->main_h = (CALENDAR_MARGIN + calendar_margin + + 6 * (priv->max_day_char_ascent + + priv->max_day_char_descent + + 2 * (focus_padding + focus_width)) + + DAY_YSEP * 5); + + height = (priv->header_h + priv->day_name_h + + priv->main_h); + + requisition->height = height + (widget->style->ythickness + INNER_BORDER) * 2; + + g_object_unref (layout); +} +static void +gtk_calendar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + gint xthickness = widget->style->xthickness; + gint ythickness = widget->style->xthickness; + gboolean year_left; + guint i; + + widget->allocation = *allocation; + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - year_left = private_data->year_before; + year_left = priv->year_before; else - year_left = !private_data->year_before; + year_left = !priv->year_before; if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) { - private_data->day_width = (private_data->min_day_width - * ((allocation->width - (xthickness + INNER_BORDER) * 2 - - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2)) - / (7 * private_data->min_day_width + private_data->max_week_char_width * 2)); - private_data->week_width = ((allocation->width - (xthickness + INNER_BORDER) * 2 - - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2 ) - - private_data->day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP); + priv->day_width = (priv->min_day_width + * ((allocation->width - (xthickness + INNER_BORDER) * 2 + - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2)) + / (7 * priv->min_day_width + priv->max_week_char_width * 2)); + priv->week_width = ((allocation->width - (xthickness + INNER_BORDER) * 2 + - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2 ) + - priv->day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP); } else { - private_data->day_width = (allocation->width - - (xthickness + INNER_BORDER) * 2 - - (CALENDAR_MARGIN * 2) - - (DAY_XSEP * 6))/7; - private_data->week_width = 0; + priv->day_width = (allocation->width + - (xthickness + INNER_BORDER) * 2 + - (CALENDAR_MARGIN * 2) + - (DAY_XSEP * 6))/7; + priv->week_width = 0; } if (GTK_WIDGET_REALIZED (widget)) @@ -1590,203 +1697,107 @@ gtk_calendar_size_allocate (GtkWidget *widget, gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); - if (private_data->header_win) - gdk_window_move_resize (private_data->header_win, + if (priv->header_win) + gdk_window_move_resize (priv->header_win, xthickness, ythickness, - allocation->width - 2 * xthickness, private_data->header_h); - if (private_data->arrow_win[ARROW_MONTH_LEFT]) - { - if (year_left) - gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT], - (allocation->width - 2 * xthickness - - (3 + 2*private_data->arrow_width - + private_data->max_month_width)), - 3, - private_data->arrow_width, - private_data->header_h - 7); - else - gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT], - 3, 3, - private_data->arrow_width, - private_data->header_h - 7); - } - if (private_data->arrow_win[ARROW_MONTH_RIGHT]) - { - if (year_left) - gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT], - (allocation->width - 2 * xthickness - - 3 - private_data->arrow_width), - 3, - private_data->arrow_width, - private_data->header_h - 7); - else - gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT], - (private_data->arrow_width - + private_data->max_month_width), - 3, - private_data->arrow_width, - private_data->header_h - 7); - } - if (private_data->arrow_win[ARROW_YEAR_LEFT]) - { - if (year_left) - gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT], - 3, 3, - private_data->arrow_width, - private_data->header_h - 7); - else - gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT], - (allocation->width - 2 * xthickness - - (3 + 2*private_data->arrow_width - + private_data->max_year_width)), - 3, - private_data->arrow_width, - private_data->header_h - 7); - } - if (private_data->arrow_win[ARROW_YEAR_RIGHT]) + allocation->width - 2 * xthickness, priv->header_h); + + for (i = 0 ; i < 4 ; i++) { - if (year_left) - gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT], - (private_data->arrow_width - + private_data->max_year_width), - 3, - private_data->arrow_width, - private_data->header_h - 7); - else - gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT], - (allocation->width - 2 * xthickness - - 3 - private_data->arrow_width), - 3, - private_data->arrow_width, - private_data->header_h - 7); + if (priv->arrow_win[i]) + { + GdkRectangle rect; + calendar_arrow_rectangle (calendar, i, &rect); + + gdk_window_move_resize (priv->arrow_win[i], + rect.x, rect.y, rect.width, rect.height); + } } - if (private_data->day_name_win) - gdk_window_move_resize (private_data->day_name_win, + + if (priv->day_name_win) + gdk_window_move_resize (priv->day_name_win, xthickness + INNER_BORDER, - private_data->header_h + (widget->style->ythickness + INNER_BORDER), + priv->header_h + (widget->style->ythickness + INNER_BORDER), allocation->width - (xthickness + INNER_BORDER) * 2, - private_data->day_name_h); + priv->day_name_h); if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) { - if (private_data->week_win) - gdk_window_move_resize (private_data->week_win, + if (priv->week_win) + gdk_window_move_resize (priv->week_win, (xthickness + INNER_BORDER), - private_data->header_h + private_data->day_name_h + priv->header_h + priv->day_name_h + (widget->style->ythickness + INNER_BORDER), - private_data->week_width, - private_data->main_h); - gdk_window_move_resize (private_data->main_win, - private_data->week_width + (xthickness + INNER_BORDER), - private_data->header_h + private_data->day_name_h + priv->week_width, + priv->main_h); + gdk_window_move_resize (priv->main_win, + priv->week_width + (xthickness + INNER_BORDER), + priv->header_h + priv->day_name_h + (widget->style->ythickness + INNER_BORDER), allocation->width - - private_data->week_width + - priv->week_width - (xthickness + INNER_BORDER) * 2, - private_data->main_h); + priv->main_h); } else { - gdk_window_move_resize (private_data->main_win, + gdk_window_move_resize (priv->main_win, (xthickness + INNER_BORDER), - private_data->header_h + private_data->day_name_h + priv->header_h + priv->day_name_h + (widget->style->ythickness + INNER_BORDER), allocation->width - - private_data->week_width + - priv->week_width - (xthickness + INNER_BORDER) * 2, - private_data->main_h); - if (private_data->week_win) - gdk_window_move_resize (private_data->week_win, + priv->main_h); + if (priv->week_win) + gdk_window_move_resize (priv->week_win, allocation->width - - private_data->week_width + - priv->week_width - (xthickness + INNER_BORDER), - private_data->header_h + private_data->day_name_h + priv->header_h + priv->day_name_h + (widget->style->ythickness + INNER_BORDER), - private_data->week_width, - private_data->main_h); + priv->week_width, + priv->main_h); } } } -static gboolean -gtk_calendar_expose (GtkWidget *widget, - GdkEventExpose *event) + +/**************************************** + * Repainting * + ****************************************/ + +static void +calendar_paint_header (GtkCalendar *calendar) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + cairo_t *cr; + char buffer[255]; + int x, y; + gint header_width, cal_height; + gint max_month_width; + gint max_year_width; + PangoLayout *layout; + PangoRectangle logical_rect; + gboolean year_left; - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (GTK_WIDGET_DRAWABLE (widget)) - { - if (event->window == private_data->main_win) - gtk_calendar_paint_main (widget); - - if (event->window == private_data->header_win) - gtk_calendar_paint_header (widget); - - if (event->window == private_data->day_name_win) - gtk_calendar_paint_day_names (widget); - - if (event->window == private_data->week_win) - gtk_calendar_paint_week_numbers (widget); - if (event->window == widget->window) - { - gtk_paint_shadow (widget->style, widget->window, GTK_WIDGET_STATE (widget), - GTK_SHADOW_IN, NULL, widget, "calendar", - 0, 0, widget->allocation.width, widget->allocation.height); - } - } - - return FALSE; -} - -static void -gtk_calendar_paint_header (GtkWidget *widget) -{ - GtkCalendar *calendar; - GdkGC *gc; - char buffer[255]; - int x, y; - gint header_width, cal_height; - gint max_month_width; - gint max_year_width; - GtkCalendarPrivateData *private_data; - PangoLayout *layout; - PangoRectangle logical_rect; - gboolean year_left; - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (private_data->freeze_count) - { - private_data->dirty_header = 1; - return; - } - - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - year_left = private_data->year_before; - else - year_left = !private_data->year_before; - - private_data->dirty_header = 0; - gc = calendar->gc; - - /* Clear window */ - gdk_window_clear (private_data->header_win); + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + year_left = priv->year_before; + else + year_left = !priv->year_before; + + cr = gdk_cairo_create (priv->header_win); header_width = widget->allocation.width - 2 * widget->style->xthickness; cal_height = widget->allocation.height; - max_month_width = private_data->max_month_width; - max_year_width = private_data->max_year_width; + max_month_width = priv->max_month_width; + max_year_width = priv->max_year_width; - gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar))); - gtk_paint_shadow (widget->style, private_data->header_win, + gtk_paint_shadow (widget->style, priv->header_win, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, widget, "calendar", - 0, 0, header_width, private_data->header_h); + 0, 0, header_width, priv->header_h); g_snprintf (buffer, sizeof (buffer), "%d", calendar->year); @@ -1794,7 +1805,7 @@ gtk_calendar_paint_header (GtkWidget *widget) pango_layout_get_pixel_extents (layout, NULL, &logical_rect); /* Draw title */ - y = (private_data->header_h - logical_rect.height) / 2; + y = (priv->header_h - logical_rect.height) / 2; /* Draw year and its arrows */ @@ -1806,14 +1817,15 @@ gtk_calendar_paint_header (GtkWidget *widget) - (max_year_width - logical_rect.width)/2); else if (year_left) - x = 3 + private_data->arrow_width + (max_year_width - logical_rect.width)/2; + x = 3 + priv->arrow_width + (max_year_width - logical_rect.width)/2; else - x = header_width - (3 + private_data->arrow_width + max_year_width + x = header_width - (3 + priv->arrow_width + max_year_width - (max_year_width - logical_rect.width)/2); - - gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar))); - gdk_draw_layout (private_data->header_win, gc, x, y, layout); + + gdk_cairo_set_source_color (cr, HEADER_FG_COLOR (GTK_WIDGET (calendar))); + cairo_move_to (cr, x, y); + pango_cairo_show_layout (cr, layout); /* Draw month */ g_snprintf (buffer, sizeof (buffer), "%s", default_monthname[calendar->month]); @@ -1828,28 +1840,24 @@ gtk_calendar_paint_header (GtkWidget *widget) x = 3 + (max_month_width - logical_rect.width) / 2; else if (year_left) - x = header_width - (3 + private_data->arrow_width + max_month_width + x = header_width - (3 + priv->arrow_width + max_month_width - (max_month_width - logical_rect.width)/2); else - x = 3 + private_data->arrow_width + (max_month_width - logical_rect.width)/2; + x = 3 + priv->arrow_width + (max_month_width - logical_rect.width)/2; - gdk_draw_layout (private_data->header_win, gc, x, y, layout); - - gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar))); - - gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT); - gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT); - gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT); - gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT); + cairo_move_to (cr, x, y); + pango_cairo_show_layout (cr, layout); g_object_unref (layout); + cairo_destroy (cr); } static void -gtk_calendar_paint_day_names (GtkWidget *widget) +calendar_paint_day_names (GtkCalendar *calendar) { - GtkCalendar *calendar; - GdkGC *gc; + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + cairo_t *cr; char buffer[255]; int day,i; int day_width, cal_width; @@ -1857,37 +1865,17 @@ gtk_calendar_paint_day_names (GtkWidget *widget) int day_wid_sep; PangoLayout *layout; PangoRectangle logical_rect; - GtkCalendarPrivateData *private_data; gint focus_padding; gint focus_width; - g_return_if_fail (GTK_IS_CALENDAR (widget)); - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - gc = calendar->gc; + cr = gdk_cairo_create (priv->day_name_win); gtk_widget_style_get (GTK_WIDGET (widget), "focus-line-width", &focus_width, "focus-padding", &focus_padding, NULL); - /* - * Handle freeze/thaw functionality - */ - - if (private_data->freeze_count) - { - private_data->dirty_day_names = 1; - return; - } - private_data->dirty_day_names = 0; - - /* - * Clear the window - */ - gdk_window_clear (private_data->day_name_win); - - day_width = private_data->day_width; + day_width = priv->day_width; cal_width = widget->allocation.width; cal_height = widget->allocation.height; day_wid_sep = day_width + DAY_XSEP; @@ -1895,113 +1883,98 @@ gtk_calendar_paint_day_names (GtkWidget *widget) /* * Draw rectangles as inverted background for the labels. */ - - gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget)); - gdk_draw_rectangle (private_data->day_name_win, gc, TRUE, - CALENDAR_MARGIN, CALENDAR_MARGIN, - cal_width-CALENDAR_MARGIN * 2, - private_data->day_name_h - CALENDAR_MARGIN); + + gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget)); + cairo_rectangle (cr, + CALENDAR_MARGIN, CALENDAR_MARGIN, + cal_width-CALENDAR_MARGIN * 2, + priv->day_name_h - CALENDAR_MARGIN); + cairo_fill (cr); if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) - gdk_draw_rectangle (private_data->day_name_win, gc, TRUE, - CALENDAR_MARGIN, - private_data->day_name_h - CALENDAR_YSEP, - private_data->week_width - CALENDAR_YSEP - CALENDAR_MARGIN, - CALENDAR_YSEP); + { + cairo_rectangle (cr, + CALENDAR_MARGIN, + priv->day_name_h - CALENDAR_YSEP, + priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN, + CALENDAR_YSEP); + cairo_fill (cr); + } /* * Write the labels */ layout = gtk_widget_create_pango_layout (widget, NULL); - - gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); + + gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget)); for (i = 0; i < 7; i++) { if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL) day = 6 - i; else day = i; - day = (day + private_data->week_start) % 7; + day = (day + priv->week_start) % 7; g_snprintf (buffer, sizeof (buffer), "%s", default_abbreviated_dayname[day]); pango_layout_set_text (layout, buffer, -1); pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - gdk_draw_layout (private_data->day_name_win, gc, - (CALENDAR_MARGIN + - + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? - (private_data->week_width + (private_data->week_width ? CALENDAR_XSEP : 0)) - : 0) - + day_wid_sep * i - + (day_width - logical_rect.width)/2), - CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y, - layout); + cairo_move_to (cr, + (CALENDAR_MARGIN + + + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? + (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0)) + : 0) + + day_wid_sep * i + + (day_width - logical_rect.width)/2), + CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y); + pango_cairo_show_layout (cr, layout); } g_object_unref (layout); + cairo_destroy (cr); } static void -gtk_calendar_paint_week_numbers (GtkWidget *widget) +calendar_paint_week_numbers (GtkCalendar *calendar) { - GtkCalendar *calendar; - GdkGC *gc; + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + cairo_t *cr; gint row, week = 0, year; gint x_loc; char buffer[3]; gint y_loc, day_height; - GtkCalendarPrivateData *private_data; PangoLayout *layout; PangoRectangle logical_rect; gint focus_padding; gint focus_width; - g_return_if_fail (GTK_IS_CALENDAR (widget)); - g_return_if_fail (widget->window != NULL); - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - gc = calendar->gc; - - /* - * Handle freeze/thaw functionality - */ - - if (private_data->freeze_count) - { - private_data->dirty_week = 1; - return; - } - private_data->dirty_week = 0; + cr = gdk_cairo_create (priv->week_win); gtk_widget_style_get (GTK_WIDGET (widget), "focus-line-width", &focus_width, "focus-padding", &focus_padding, NULL); - /* - * Clear the window - */ - - gdk_window_clear (private_data->week_win); - /* * Draw a rectangle as inverted background for the labels. */ - - gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget)); - if (private_data->day_name_win) - gdk_draw_rectangle (private_data->week_win, gc, TRUE, - CALENDAR_MARGIN, - 0, - private_data->week_width - CALENDAR_MARGIN, - private_data->main_h - CALENDAR_MARGIN); + + gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget)); + if (priv->day_name_win) + cairo_rectangle (cr, + CALENDAR_MARGIN, + 0, + priv->week_width - CALENDAR_MARGIN, + priv->main_h - CALENDAR_MARGIN); else - gdk_draw_rectangle (private_data->week_win, gc, TRUE, - CALENDAR_MARGIN, - CALENDAR_MARGIN, - private_data->week_width - CALENDAR_MARGIN, - private_data->main_h - 2 * CALENDAR_MARGIN); + cairo_rectangle (cr, + CALENDAR_MARGIN, + CALENDAR_MARGIN, + priv->week_width - CALENDAR_MARGIN, + priv->main_h - 2 * CALENDAR_MARGIN); + cairo_fill (cr); /* * Write the labels @@ -2009,45 +1982,45 @@ gtk_calendar_paint_week_numbers (GtkWidget *widget) layout = gtk_widget_create_pango_layout (widget, NULL); - gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); - day_height = row_height (calendar); + gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget)); + day_height = calendar_row_height (calendar); for (row = 0; row < 6; row++) { + gboolean result; + year = calendar->year; if (calendar->day[row][6] < 15 && row > 3 && calendar->month == 11) year++; - g_return_if_fail (week_of_year (&week, &year, - ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0) - + calendar->month) % 12 + 1, calendar->day[row][6])); + result = week_of_year (&week, &year, + ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0) + + calendar->month) % 12 + 1, calendar->day[row][6]); + g_return_if_fail (result); g_snprintf (buffer, sizeof (buffer), "%d", week); pango_layout_set_text (layout, buffer, -1); pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - y_loc = top_y_for_row (calendar, row) + (day_height - logical_rect.height) / 2; + y_loc = calendar_top_y_for_row (calendar, row) + (day_height - logical_rect.height) / 2; - x_loc = (private_data->week_width + x_loc = (priv->week_width - logical_rect.width - CALENDAR_XSEP - focus_padding - focus_width); - gdk_draw_layout (private_data->week_win, gc, x_loc, y_loc, layout); + cairo_move_to (cr, x_loc, y_loc); + pango_cairo_show_layout (cr, layout); } g_object_unref (layout); + cairo_destroy (cr); } static void -gtk_calendar_paint_day_num (GtkWidget *widget, - gint day) +calendar_invalidate_day_num (GtkCalendar *calendar, + gint day) { - GtkCalendar *calendar; gint r, c, row, col; - g_return_if_fail (GTK_IS_CALENDAR (widget)); - - calendar = GTK_CALENDAR (widget); - row = -1; col = -1; for (r = 0; r < 6; r++) @@ -2062,114 +2035,101 @@ gtk_calendar_paint_day_num (GtkWidget *widget, g_return_if_fail (row != -1); g_return_if_fail (col != -1); - gtk_calendar_paint_day (widget, row, col); + calendar_invalidate_day (calendar, row, col); } static void -gtk_calendar_paint_day (GtkWidget *widget, - gint row, - gint col) +calendar_invalidate_day (GtkCalendar *calendar, + gint row, + gint col) { - GtkCalendar *calendar; - GdkGC *gc; + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + + if (priv->main_win) + { + GdkRectangle day_rect; + + calendar_day_rectangle (calendar, row, col, &day_rect); + gdk_window_invalidate_rect (priv->main_win, &day_rect, FALSE); + } +} + +static void +calendar_paint_day (GtkCalendar *calendar, + gint row, + gint col) +{ + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + cairo_t *cr; + GdkColor *text_color; gchar buffer[255]; gint day; - gint day_height; - gint x_left; - gint x_loc; - gint y_top; - gint y_loc; - gint day_xspace; - gint focus_width; + gint x_loc, y_loc; + GdkRectangle day_rect; - GtkCalendarPrivateData *private_data; PangoLayout *layout; PangoRectangle logical_rect; - g_return_if_fail (GTK_IS_CALENDAR (widget)); g_return_if_fail (row < 6); g_return_if_fail (col < 7); - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - /* - * Handle freeze/thaw functionality - */ - - if (private_data->freeze_count) - { - private_data->dirty_main = 1; - return; - } - - gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL); + cr = gdk_cairo_create (priv->main_win); - day_height = row_height (calendar); - - day_xspace = private_data->day_width - private_data->max_day_char_width*2; - day = calendar->day[row][col]; - - x_left = left_x_for_column (calendar, col); - x_loc = x_left + private_data->day_width / 2 + private_data->max_day_char_width; - - y_top = top_y_for_row (calendar, row); - - gdk_window_clear_area (private_data->main_win, x_left, y_top, - private_data->day_width, day_height); - - gc = calendar->gc; + + calendar_day_rectangle (calendar, row, col, &day_rect); if (calendar->day_month[row][col] == MONTH_PREV) { - gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar))); + text_color = PREV_MONTH_COLOR (widget); } else if (calendar->day_month[row][col] == MONTH_NEXT) { - gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar))); + text_color = NEXT_MONTH_COLOR (widget); } else { /* if (calendar->highlight_row == row && calendar->highlight_col == col) { - gdk_gc_set_foreground (gc, HIGHLIGHT_BACK_COLOR (GTK_WIDGET (calendar))); - gdk_draw_rectangle (private_data->main_win, gc, TRUE, x_left, y_top, - private_data->day_width, day_height); + cairo_set_source_color (cr, HIGHLIGHT_BG_COLOR (widget)); + gdk_cairo_rectangle (cr, &day_rect); + cairo_fill (cr); } */ if (calendar->selected_day == day) { - gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (GTK_WIDGET (calendar))); - gdk_draw_rectangle (private_data->main_win, gc, TRUE, x_left, y_top, - private_data->day_width, day_height); + gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget)); + gdk_cairo_rectangle (cr, &day_rect); + cairo_fill (cr); } - - if (calendar->marked_date[day-1]) - gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar))); - else - gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar))); - if (calendar->selected_day == day) - gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (GTK_WIDGET (calendar))); + text_color = SELECTED_FG_COLOR (widget); + else if (calendar->marked_date[day-1]) + text_color = MARKED_COLOR (widget); else - gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->fg[GTK_WIDGET_STATE (calendar)])); + text_color = NORMAL_DAY_COLOR (widget); } - g_snprintf (buffer, sizeof (buffer), "%d", day); layout = gtk_widget_create_pango_layout (widget, buffer); pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + x_loc = day_rect.x + day_rect.width / 2 + priv->max_day_char_width; x_loc -= logical_rect.width; - - y_loc = y_top + (day_height - logical_rect.height) / 2; - gdk_draw_layout (private_data->main_win, gc, - x_loc, y_loc, layout); + y_loc = day_rect.y + (day_rect.height - logical_rect.height) / 2; + + gdk_cairo_set_source_color (cr, text_color); + cairo_move_to (cr, x_loc, y_loc); + pango_cairo_show_layout (cr, layout); + if (calendar->marked_date[day-1] && calendar->day_month[row][col] == MONTH_CURRENT) - gdk_draw_layout (private_data->main_win, gc, - x_loc-1, y_loc, layout); + { + cairo_move_to (cr, x_loc - 1, y_loc); + pango_cairo_show_layout (cr, layout); + } if (GTK_WIDGET_HAS_FOCUS (calendar) && calendar->focus_row == row && calendar->focus_col == col) @@ -2182,593 +2142,280 @@ gtk_calendar_paint_day (GtkWidget *widget, state = GTK_STATE_NORMAL; gtk_paint_focus (widget->style, - private_data->main_win, + priv->main_win, (calendar->selected_day == day) ? GTK_STATE_SELECTED : GTK_STATE_NORMAL, NULL, widget, "calendar-day", - x_left, y_top, - private_data->day_width, - day_height); + day_rect.x, day_rect.y, + day_rect.width, day_rect.height); } g_object_unref (layout); + cairo_destroy (cr); } - static void -gtk_calendar_paint_main (GtkWidget *widget) +calendar_paint_main (GtkCalendar *calendar) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; gint row, col; - g_return_if_fail (GTK_IS_CALENDAR (widget)); - g_return_if_fail (widget->window != NULL); - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (private_data->freeze_count) - { - private_data->dirty_main = 1; - return; - } - private_data->dirty_main = 0; - gdk_window_clear (private_data->main_win); - - /* gtk_calendar_compute_days (calendar); */ /* REMOVE later */ - for (col = 0; col < 7; col++) for (row = 0; row < 6; row++) - gtk_calendar_paint_day (widget, row, col); + calendar_paint_day (calendar, row, col); } static void -gtk_calendar_compute_days (GtkCalendar *calendar) +calendar_invalidate_arrow (GtkCalendar *calendar, + guint arrow) { - GtkCalendarPrivateData *private_data; - gint month; - gint year; - gint ndays_in_month; - gint ndays_in_prev_month; - gint first_day; - gint row; - gint col; - gint day; - - g_return_if_fail (GTK_IS_CALENDAR (calendar)); - - private_data = GTK_CALENDAR_PRIVATE_DATA (GTK_WIDGET (calendar)); - - year = calendar->year; - month = calendar->month + 1; - - ndays_in_month = month_length[leap (year)][month]; - - first_day = day_of_week (year, month, 1); - first_day = (first_day + 7 - private_data->week_start) % 7; + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + GdkWindow *window; - /* Compute days of previous month */ - if (month > 1) - ndays_in_prev_month = month_length[leap (year)][month-1]; - else - ndays_in_prev_month = month_length[leap (year)][12]; - day = ndays_in_prev_month - first_day + 1; + window = priv->arrow_win[arrow]; + if (window) + gdk_window_invalidate_rect (window, NULL, FALSE); +} + +static void +calendar_paint_arrow (GtkCalendar *calendar, + guint arrow) +{ + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + GdkWindow *window; - row = 0; - if (first_day > 0) + window = priv->arrow_win[arrow]; + if (window) { - for (col = 0; col < first_day; col++) - { - calendar->day[row][col] = day; - calendar->day_month[row][col] = MONTH_PREV; - day++; - } + cairo_t *cr = gdk_cairo_create (window); + gint width, height; + gint state; + + state = priv->arrow_state[arrow]; + + gdk_cairo_set_source_color (cr, &widget->style->bg[state]); + cairo_paint (cr); + + gdk_drawable_get_size (window, &width, &height); + if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT) + gtk_paint_arrow (widget->style, window, state, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_LEFT, TRUE, + width/2 - 3, height/2 - 4, 8, 8); + else + gtk_paint_arrow (widget->style, window, state, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_RIGHT, TRUE, + width/2 - 2, height/2 - 4, 8, 8); } - - /* Compute days of current month */ - col = first_day; - for (day = 1; day <= ndays_in_month; day++) +} + +static gboolean +gtk_calendar_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + int i; + + if (GTK_WIDGET_DRAWABLE (widget)) { - calendar->day[row][col] = day; - calendar->day_month[row][col] = MONTH_CURRENT; + if (event->window == priv->main_win) + calendar_paint_main (calendar); - col++; - if (col == 7) + if (event->window == priv->header_win) + calendar_paint_header (calendar); + + for (i = 0; i < 4; i++) + if (event->window == priv->arrow_win[i]) + calendar_paint_arrow (calendar, i); + + if (event->window == priv->day_name_win) + calendar_paint_day_names (calendar); + + if (event->window == priv->week_win) + calendar_paint_week_numbers (calendar); + if (event->window == widget->window) { - row++; - col = 0; + gtk_paint_shadow (widget->style, widget->window, GTK_WIDGET_STATE (widget), + GTK_SHADOW_IN, NULL, widget, "calendar", + 0, 0, widget->allocation.width, widget->allocation.height); } } - /* Compute days of next month */ - day = 1; - for (; row <= 5; row++) - { - for (; col <= 6; col++) - { - calendar->day[row][col] = day; - calendar->day_month[row][col] = MONTH_NEXT; - day++; - } - col = 0; - } + return FALSE; } -void -gtk_calendar_display_options (GtkCalendar *calendar, - GtkCalendarDisplayOptions flags) + +/**************************************** + * Mouse handling * + ****************************************/ + +#define CALENDAR_INITIAL_TIMER_DELAY 200 +#define CALENDAR_TIMER_DELAY 20 + +static void +calendar_arrow_action (GtkCalendar *calendar, + guint arrow) { - gtk_calendar_set_display_options (calendar, flags); + switch (arrow) + { + case ARROW_YEAR_LEFT: + calendar_set_year_prev (calendar); + break; + case ARROW_YEAR_RIGHT: + calendar_set_year_next (calendar); + break; + case ARROW_MONTH_LEFT: + calendar_set_month_prev (calendar); + break; + case ARROW_MONTH_RIGHT: + calendar_set_month_next (calendar); + break; + default:; + /* do nothing */ + } } -/** - * gtk_calendar_get_display_options: - * @calendar: a #GtkCalendar - * - * Returns the current display options of @calendar. - * - * Return value: the display options. - * - * Since: 2.4 - **/ -GtkCalendarDisplayOptions -gtk_calendar_get_display_options (GtkCalendar *calendar) +static gboolean +calendar_timer (gpointer data) { - g_return_val_if_fail (GTK_IS_CALENDAR (calendar), 0); - - return calendar->display_flags; -} - -/** - * gtk_calendar_set_display_options: - * @calendar: a #GtkCalendar - * @flags: the display options to set - * - * Sets display options (whether to display the heading and the month - * headings). - * - * Since: 2.4 - **/ -void -gtk_calendar_set_display_options (GtkCalendar *calendar, - GtkCalendarDisplayOptions flags) -{ - GtkCalendarPrivateData *private_data; - gint resize = 0; - GtkWidget *widget; - gint i; - GtkCalendarDisplayOptions old_flags; - - g_return_if_fail (GTK_IS_CALENDAR (calendar)); - - widget = GTK_WIDGET (calendar); - private_data = GTK_CALENDAR_PRIVATE_DATA (calendar); - old_flags = calendar->display_flags; + GtkCalendar *calendar = data; + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + gboolean retval = FALSE; - if (GTK_WIDGET_REALIZED (widget)) + GDK_THREADS_ENTER (); + + if (priv->timer) { - if ((flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE) - { - resize ++; - if (! (flags & GTK_CALENDAR_NO_MONTH_CHANGE) - && (private_data->header_win)) - { - calendar->display_flags &= ~GTK_CALENDAR_NO_MONTH_CHANGE; - gtk_calendar_realize_arrows (widget); - } - else - { - for (i = 0; i < 4; i++) - { - if (private_data->arrow_win[i]) - { - gdk_window_set_user_data (private_data->arrow_win[i], - NULL); - gdk_window_destroy (private_data->arrow_win[i]); - private_data->arrow_win[i] = NULL; - } - } - } - } - - if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING) - { - resize++; - - if (flags & GTK_CALENDAR_SHOW_HEADING) - { - calendar->display_flags |= GTK_CALENDAR_SHOW_HEADING; - gtk_calendar_realize_header (widget); - } - else - { - for (i = 0; i < 4; i++) - { - if (private_data->arrow_win[i]) - { - gdk_window_set_user_data (private_data->arrow_win[i], - NULL); - gdk_window_destroy (private_data->arrow_win[i]); - private_data->arrow_win[i] = NULL; - } - } - gdk_window_set_user_data (private_data->header_win, NULL); - gdk_window_destroy (private_data->header_win); - private_data->header_win = NULL; - } - } - - - if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES) - { - resize++; - - if (flags & GTK_CALENDAR_SHOW_DAY_NAMES) - { - calendar->display_flags |= GTK_CALENDAR_SHOW_DAY_NAMES; - gtk_calendar_realize_day_names (widget); - } - else - { - gdk_window_set_user_data (private_data->day_name_win, NULL); - gdk_window_destroy (private_data->day_name_win); - private_data->day_name_win = NULL; - } - } - - if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS) + calendar_arrow_action (calendar, priv->click_child); + + if (priv->need_timer) { - resize++; - - if (flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) - { - calendar->display_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS; - gtk_calendar_realize_week_numbers (widget); - } - else - { - gdk_window_set_user_data (private_data->week_win, NULL); - gdk_window_destroy (private_data->week_win); - private_data->week_win = NULL; - } + priv->need_timer = FALSE; + priv->timer = g_timeout_add (CALENDAR_TIMER_DELAY, + (GSourceFunc) calendar_timer, + (gpointer) calendar); } + else + retval = TRUE; + } - if ((flags ^ calendar->display_flags) & GTK_CALENDAR_WEEK_START_MONDAY) - g_warning ("GTK_CALENDAR_WEEK_START_MONDAY is ignored; the first day of the week is determined from the locale"); - - calendar->display_flags = flags; - if (resize) - gtk_widget_queue_resize (GTK_WIDGET (calendar)); - - } - else - calendar->display_flags = flags; - - g_object_freeze_notify (G_OBJECT (calendar)); - if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING) - g_object_notify (G_OBJECT (calendar), "show-heading"); - if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES) - g_object_notify (G_OBJECT (calendar), "show-day-names"); - if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE) - g_object_notify (G_OBJECT (calendar), "no-month-change"); - if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS) - g_object_notify (G_OBJECT (calendar), "show-week-numbers"); - g_object_thaw_notify (G_OBJECT (calendar)); -} - -gboolean -gtk_calendar_select_month (GtkCalendar *calendar, - guint month, - guint year) -{ - g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE); - g_return_val_if_fail (month <= 11, FALSE); - - calendar->month = month; - calendar->year = year; - - gtk_calendar_compute_days (calendar); - - gtk_widget_queue_draw (GTK_WIDGET (calendar)); - - g_object_freeze_notify (G_OBJECT (calendar)); - g_object_notify (G_OBJECT (calendar), "month"); - g_object_notify (G_OBJECT (calendar), "year"); - g_object_thaw_notify (G_OBJECT (calendar)); + GDK_THREADS_LEAVE (); - g_signal_emit (calendar, - gtk_calendar_signals[MONTH_CHANGED_SIGNAL], - 0); - return TRUE; + return retval; } -void -gtk_calendar_select_day (GtkCalendar *calendar, - guint day) +static void +calendar_start_spinning (GtkCalendar *calendar, + gint click_child) { - g_return_if_fail (GTK_IS_CALENDAR (calendar)); - g_return_if_fail (day <= 31); - - /* gtk_calendar_compute_days (calendar); */ - - /* Deselect the old day */ - if (calendar->selected_day > 0) - { - gint selected_day; - - selected_day = calendar->selected_day; - calendar->selected_day = 0; - if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) - gtk_calendar_paint_day_num (GTK_WIDGET (calendar), selected_day); - } - - calendar->selected_day = day; + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + + priv->click_child = click_child; - /* Select the new day */ - if (day != 0) + if (!priv->timer) { - if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) - gtk_calendar_paint_day_num (GTK_WIDGET (calendar), day); + priv->need_timer = TRUE; + priv->timer = g_timeout_add (CALENDAR_INITIAL_TIMER_DELAY, + calendar_timer, + calendar); } - - g_object_notify (G_OBJECT (calendar), "day"); - - g_signal_emit (calendar, - gtk_calendar_signals[DAY_SELECTED_SIGNAL], - 0); } static void -gtk_calendar_select_and_focus_day (GtkCalendar *calendar, - guint day) +calendar_stop_spinning (GtkCalendar *calendar) { - gint old_focus_row = calendar->focus_row; - gint old_focus_col = calendar->focus_col; - gint row; - gint col; - - for (row = 0; row < 6; row ++) - for (col = 0; col < 7; col++) - { - if (calendar->day_month[row][col] == MONTH_CURRENT - && calendar->day[row][col] == day) - { - calendar->focus_row = row; - calendar->focus_col = col; - } - } + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); - if (old_focus_row != -1 && old_focus_col != -1) - gtk_calendar_paint_day (GTK_WIDGET (calendar), old_focus_row, old_focus_col); - - gtk_calendar_select_day (calendar, day); + if (priv->timer) + { + g_source_remove (priv->timer); + priv->timer = 0; + priv->need_timer = FALSE; + } } -void -gtk_calendar_clear_marks (GtkCalendar *calendar) +static void +calendar_main_button_press (GtkCalendar *calendar, + GdkEventButton *event) { - guint day; + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + gint x, y; + gint row, col; + gint day_month; + gint day; - g_return_if_fail (GTK_IS_CALENDAR (calendar)); + x = (gint) (event->x); + y = (gint) (event->y); - for (day = 0; day < 31; day++) - { - calendar->marked_date[day] = FALSE; - } - - calendar->num_marked_dates = 0; - - if (GTK_WIDGET_DRAWABLE (calendar)) - { - gtk_calendar_paint_main (GTK_WIDGET (calendar)); - } -} + row = calendar_row_from_y (calendar, y); + col = calendar_column_from_x (calendar, x); -gboolean -gtk_calendar_mark_day (GtkCalendar *calendar, - guint day) -{ - g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE); + /* If row or column isn't found, just return. */ + if (row == -1 || col == -1) + return; - if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == FALSE) + day_month = calendar->day_month[row][col]; + + if (event->type == GDK_BUTTON_PRESS) { - calendar->marked_date[day - 1] = TRUE; - calendar->num_marked_dates++; + day = calendar->day[row][col]; + + if (day_month == MONTH_PREV) + calendar_set_month_prev (calendar); + else if (day_month == MONTH_NEXT) + calendar_set_month_next (calendar); + + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); + + if (event->button == 1) + { + priv->in_drag = 1; + priv->drag_start_x = x; + priv->drag_start_y = y; + } + + calendar_select_and_focus_day (calendar, day); } - if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) + else if (event->type == GDK_2BUTTON_PRESS) { - gtk_calendar_paint_main (GTK_WIDGET (calendar)); + priv->in_drag = 0; + if (day_month == MONTH_CURRENT) + g_signal_emit (calendar, + gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL], + 0); } - - return TRUE; } -gboolean -gtk_calendar_unmark_day (GtkCalendar *calendar, - guint day) +static gboolean +gtk_calendar_button_press (GtkWidget *widget, + GdkEventButton *event) { - g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE); + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + gint arrow = -1; - if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == TRUE) - { - calendar->marked_date[day - 1] = FALSE; - calendar->num_marked_dates--; - } - - if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) - { - gtk_calendar_paint_main (GTK_WIDGET (calendar)); - } - - return TRUE; -} - -void -gtk_calendar_get_date (GtkCalendar *calendar, - guint *year, - guint *month, - guint *day) -{ - g_return_if_fail (GTK_IS_CALENDAR (calendar)); - - if (year) - *year = calendar->year; - - if (month) - *month = calendar->month; - - if (day) - *day = calendar->selected_day; -} - -#define CALENDAR_INITIAL_TIMER_DELAY 200 -#define CALENDAR_TIMER_DELAY 20 - -static void -arrow_action (GtkCalendar *calendar, - guint arrow) -{ - switch (arrow) - { - case ARROW_YEAR_LEFT: - gtk_calendar_set_year_prev (calendar); - break; - case ARROW_YEAR_RIGHT: - gtk_calendar_set_year_next (calendar); - break; - case ARROW_MONTH_LEFT: - gtk_calendar_set_month_prev (calendar); - break; - case ARROW_MONTH_RIGHT: - gtk_calendar_set_month_next (calendar); - break; - default:; - /* do nothing */ - } -} - -static gboolean -calendar_timer (gpointer data) -{ - GtkCalendar *calendar = data; - GtkCalendarPrivateData *private_data = GTK_CALENDAR_PRIVATE_DATA (calendar); - gboolean retval = FALSE; - - GDK_THREADS_ENTER (); - - if (private_data->timer) - { - arrow_action (calendar, private_data->click_child); - - if (private_data->need_timer) - { - private_data->need_timer = FALSE; - private_data->timer = g_timeout_add (CALENDAR_TIMER_DELAY, - (GSourceFunc) calendar_timer, - (gpointer) calendar); - } - else - retval = TRUE; - } - - GDK_THREADS_LEAVE (); - - return retval; -} - -static void -start_spinning (GtkWidget *widget, - gint click_child) -{ - GtkCalendarPrivateData *private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - private_data->click_child = click_child; - - if (!private_data->timer) - { - private_data->need_timer = TRUE; - private_data->timer = g_timeout_add (CALENDAR_INITIAL_TIMER_DELAY, - calendar_timer, - (gpointer) widget); - } -} - -static void -stop_spinning (GtkWidget *widget) -{ - GtkCalendarPrivateData *private_data; - - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (private_data->timer) - { - g_source_remove (private_data->timer); - private_data->timer = 0; - private_data->need_timer = FALSE; - } -} - -static void -gtk_calendar_destroy (GtkObject *object) -{ - stop_spinning (GTK_WIDGET (object)); - - GTK_OBJECT_CLASS (parent_class)->destroy (object); -} - -static void -gtk_calendar_grab_notify (GtkWidget *widget, - gboolean was_grabbed) -{ - if (!was_grabbed) - stop_spinning (widget); -} - -static gboolean -gtk_calendar_focus_out (GtkWidget *widget, - GdkEventFocus *event) -{ - GtkCalendarPrivateData *private_data; - - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - stop_spinning (widget); - - private_data->in_drag = 0; - - return FALSE; -} - -static gboolean -gtk_calendar_button_press (GtkWidget *widget, - GdkEventButton *event) -{ - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - gint arrow = -1; - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (event->window == private_data->main_win) - gtk_calendar_main_button (widget, event); + if (event->window == priv->main_win) + calendar_main_button_press (calendar, event); if (!GTK_WIDGET_HAS_FOCUS (widget)) gtk_widget_grab_focus (widget); for (arrow = ARROW_YEAR_LEFT; arrow <= ARROW_MONTH_RIGHT; arrow++) { - if (event->window == private_data->arrow_win[arrow]) + if (event->window == priv->arrow_win[arrow]) { /* only call the action on single click, not double */ if (event->type == GDK_BUTTON_PRESS) { if (event->button == 1) - start_spinning (widget, arrow); + calendar_start_spinning (calendar, arrow); - arrow_action (calendar, arrow); + calendar_arrow_action (calendar, arrow); } return TRUE; @@ -2782,18 +2429,15 @@ static gboolean gtk_calendar_button_release (GtkWidget *widget, GdkEventButton *event) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); if (event->button == 1) { - stop_spinning (widget); + calendar_stop_spinning (calendar); - if (private_data->in_drag) - private_data->in_drag = 0; + if (priv->in_drag) + priv->in_drag = 0; } return TRUE; @@ -2803,24 +2447,22 @@ static gboolean gtk_calendar_motion_notify (GtkWidget *widget, GdkEventMotion *event) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); gint event_x, event_y; gint row, col; gint old_row, old_col; - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); event_x = (gint) (event->x); event_y = (gint) (event->y); - if (event->window == private_data->main_win) + if (event->window == priv->main_win) { - if (private_data->in_drag) + if (priv->in_drag) { if (gtk_drag_check_threshold (widget, - private_data->drag_start_x, private_data->drag_start_y, + priv->drag_start_x, priv->drag_start_y, event->x, event->y)) { GdkDragContext *context; @@ -2830,7 +2472,7 @@ gtk_calendar_motion_notify (GtkWidget *widget, 1, (GdkEvent *)event); - private_data->in_drag = 0; + priv->in_drag = 0; gtk_target_list_unref (target_list); gtk_drag_set_icon_default (context); @@ -2838,8 +2480,8 @@ gtk_calendar_motion_notify (GtkWidget *widget, } else { - row = row_from_y (calendar, event_y); - col = column_from_x (calendar, event_x); + row = calendar_row_from_y (calendar, event_y); + col = calendar_column_from_x (calendar, event_x); if (row != calendar->highlight_row || calendar->highlight_col != col) { @@ -2849,14 +2491,14 @@ gtk_calendar_motion_notify (GtkWidget *widget, { calendar->highlight_row = -1; calendar->highlight_col = -1; - gtk_calendar_paint_day (widget, old_row, old_col); + calendar_invalidate_day (calendar, old_row, old_col); } calendar->highlight_row = row; calendar->highlight_col = col; if (row > -1 && col > -1) - gtk_calendar_paint_day (widget, row, col); + calendar_invalidate_day (calendar, row, col); } } } @@ -2867,34 +2509,31 @@ static gboolean gtk_calendar_enter_notify (GtkWidget *widget, GdkEventCrossing *event) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); - if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT]) + if (event->window == priv->arrow_win[ARROW_MONTH_LEFT]) { - private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT; - gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT); + priv->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT; + calendar_invalidate_arrow (calendar, ARROW_MONTH_LEFT); } - if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT]) + if (event->window == priv->arrow_win[ARROW_MONTH_RIGHT]) { - private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT; - gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT); + priv->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT; + calendar_invalidate_arrow (calendar, ARROW_MONTH_RIGHT); } - if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT]) + if (event->window == priv->arrow_win[ARROW_YEAR_LEFT]) { - private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT; - gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT); + priv->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT; + calendar_invalidate_arrow (calendar, ARROW_YEAR_LEFT); } - if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT]) + if (event->window == priv->arrow_win[ARROW_YEAR_RIGHT]) { - private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT; - gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT); + priv->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT; + calendar_invalidate_arrow (calendar, ARROW_YEAR_RIGHT); } return TRUE; @@ -2904,212 +2543,48 @@ static gboolean gtk_calendar_leave_notify (GtkWidget *widget, GdkEventCrossing *event) { - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); gint row; gint col; - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (event->window == private_data->main_win) + if (event->window == priv->main_win) { row = calendar->highlight_row; col = calendar->highlight_col; calendar->highlight_row = -1; calendar->highlight_col = -1; if (row > -1 && col > -1) - gtk_calendar_paint_day (widget, row, col); + calendar_invalidate_day (calendar, row, col); } - if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT]) + if (event->window == priv->arrow_win[ARROW_MONTH_LEFT]) { - private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL; - gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT); + priv->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL; + calendar_invalidate_arrow (calendar, ARROW_MONTH_LEFT); } - if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT]) + if (event->window == priv->arrow_win[ARROW_MONTH_RIGHT]) { - private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL; - gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT); + priv->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL; + calendar_invalidate_arrow (calendar, ARROW_MONTH_RIGHT); } - if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT]) + if (event->window == priv->arrow_win[ARROW_YEAR_LEFT]) { - private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL; - gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT); + priv->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL; + calendar_invalidate_arrow (calendar, ARROW_YEAR_LEFT); } - if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT]) + if (event->window == priv->arrow_win[ARROW_YEAR_RIGHT]) { - private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL; - gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT); + priv->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL; + calendar_invalidate_arrow (calendar, ARROW_YEAR_RIGHT); } return TRUE; } -static void -gtk_calendar_paint_arrow (GtkWidget *widget, - guint arrow) -{ - GtkCalendarPrivateData *private_data; - GdkWindow *window; - GdkGC *gc; - GtkCalendar *calendar; - gint state; - gint width, height; - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (private_data->freeze_count) - { - private_data->dirty_header = 1; - return; - } - window = private_data->arrow_win[arrow]; - if (window) - { - state = private_data->arrow_state[arrow]; - gc = calendar->gc; - - gdk_window_clear (window); - gdk_window_set_background (window, &(widget)->style->bg[state]); - gdk_drawable_get_size (window, &width, &height); - gdk_window_clear_area (window, - 0,0, - width,height); - if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT) - gtk_paint_arrow (widget->style, window, state, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_LEFT, TRUE, - width/2 - 3, height/2 - 4, 8, 8); - else - gtk_paint_arrow (widget->style, window, state, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_RIGHT, TRUE, - width/2 - 2, height/2 - 4, 8, 8); - } -} - -void -gtk_calendar_freeze (GtkCalendar *calendar) -{ - g_return_if_fail (GTK_IS_CALENDAR (calendar)); - - GTK_CALENDAR_PRIVATE_DATA (calendar)->freeze_count++; -} - -void -gtk_calendar_thaw (GtkCalendar *calendar) -{ - GtkCalendarPrivateData *private_data; - - g_return_if_fail (GTK_IS_CALENDAR (calendar)); - - private_data = GTK_CALENDAR_PRIVATE_DATA (calendar); - - if (private_data->freeze_count) - if (!(--private_data->freeze_count)) - { - if (private_data->dirty_header) - if (GTK_WIDGET_DRAWABLE (calendar)) - gtk_calendar_paint_header (GTK_WIDGET (calendar)); - - if (private_data->dirty_day_names) - if (GTK_WIDGET_DRAWABLE (calendar)) - gtk_calendar_paint_day_names (GTK_WIDGET (calendar)); - - if (private_data->dirty_week) - if (GTK_WIDGET_DRAWABLE (calendar)) - gtk_calendar_paint_week_numbers (GTK_WIDGET (calendar)); - - if (private_data->dirty_main) - if (GTK_WIDGET_DRAWABLE (calendar)) - gtk_calendar_paint_main (GTK_WIDGET (calendar)); - } -} - -static void -gtk_calendar_set_background (GtkWidget *widget) -{ - GtkCalendar *calendar; - GtkCalendarPrivateData *private_data; - gint i; - - calendar = GTK_CALENDAR (widget); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (GTK_WIDGET_REALIZED (widget)) - { - for (i = 0; i < 4; i++) - { - if (private_data->arrow_win[i]) - gdk_window_set_background (private_data->arrow_win[i], - HEADER_BG_COLOR (widget)); - } - if (private_data->header_win) - gdk_window_set_background (private_data->header_win, - HEADER_BG_COLOR (widget)); - if (private_data->day_name_win) - gdk_window_set_background (private_data->day_name_win, - BACKGROUND_COLOR (widget)); - if (private_data->week_win) - gdk_window_set_background (private_data->week_win, - BACKGROUND_COLOR (widget)); - if (private_data->main_win) - gdk_window_set_background (private_data->main_win, - BACKGROUND_COLOR (widget)); - if (widget->window) - gdk_window_set_background (widget->window, - BACKGROUND_COLOR (widget)); - } -} - -static void -gtk_calendar_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - if (previous_style && GTK_WIDGET_REALIZED (widget)) - gtk_calendar_set_background(widget); -} - -static void -gtk_calendar_state_changed (GtkWidget *widget, - GtkStateType previous_state) -{ - GtkCalendarPrivateData *private_data; - int i; - - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (!GTK_WIDGET_IS_SENSITIVE (widget)) - { - private_data->in_drag = 0; - stop_spinning (widget); - } - - for (i = 0; i < 4; i++) - if (GTK_WIDGET_IS_SENSITIVE (widget)) - private_data->arrow_state[i] = GTK_STATE_NORMAL; - else - private_data->arrow_state[i] = GTK_STATE_INSENSITIVE; - - gtk_calendar_set_background (widget); -} - -static void -gtk_calendar_finalize (GObject *object) -{ - GtkCalendarPrivateData *private_data; - private_data = GTK_CALENDAR_PRIVATE_DATA (object); - - g_free (private_data); - - (* G_OBJECT_CLASS (parent_class)->finalize) (object); -} - static gboolean gtk_calendar_scroll (GtkWidget *widget, GdkEventScroll *event) @@ -3120,13 +2595,13 @@ gtk_calendar_scroll (GtkWidget *widget, { if (!GTK_WIDGET_HAS_FOCUS (widget)) gtk_widget_grab_focus (widget); - gtk_calendar_set_month_prev (calendar); + calendar_set_month_prev (calendar); } else if (event->direction == GDK_SCROLL_DOWN) { if (!GTK_WIDGET_HAS_FOCUS (widget)) gtk_widget_grab_focus (widget); - gtk_calendar_set_month_next (calendar); + calendar_set_month_next (calendar); } else return FALSE; @@ -3134,9 +2609,14 @@ gtk_calendar_scroll (GtkWidget *widget, return TRUE; } + +/**************************************** + * Key handling * + ****************************************/ + static void move_focus (GtkCalendar *calendar, - gint direction) + gint direction) { GtkTextDirection text_dir = gtk_widget_get_direction (GTK_WIDGET (calendar)); @@ -3185,54 +2665,54 @@ gtk_calendar_key_press (GtkWidget *widget, case GDK_Left: return_val = TRUE; if (event->state & GDK_CONTROL_MASK) - gtk_calendar_set_month_prev (calendar); + calendar_set_month_prev (calendar); else { move_focus (calendar, -1); - gtk_calendar_paint_day (widget, old_focus_row, old_focus_col); - gtk_calendar_paint_day (widget, calendar->focus_row, - calendar->focus_col); + calendar_invalidate_day (calendar, old_focus_row, old_focus_col); + calendar_invalidate_day (calendar, calendar->focus_row, + calendar->focus_col); } break; case GDK_KP_Right: case GDK_Right: return_val = TRUE; if (event->state & GDK_CONTROL_MASK) - gtk_calendar_set_month_next (calendar); + calendar_set_month_next (calendar); else { move_focus (calendar, 1); - gtk_calendar_paint_day (widget, old_focus_row, old_focus_col); - gtk_calendar_paint_day (widget, calendar->focus_row, - calendar->focus_col); + calendar_invalidate_day (calendar, old_focus_row, old_focus_col); + calendar_invalidate_day (calendar, calendar->focus_row, + calendar->focus_col); } break; case GDK_KP_Up: case GDK_Up: return_val = TRUE; if (event->state & GDK_CONTROL_MASK) - gtk_calendar_set_year_prev (calendar); + calendar_set_year_prev (calendar); else { if (calendar->focus_row > 0) calendar->focus_row--; - gtk_calendar_paint_day (widget, old_focus_row, old_focus_col); - gtk_calendar_paint_day (widget, calendar->focus_row, - calendar->focus_col); + calendar_invalidate_day (calendar, old_focus_row, old_focus_col); + calendar_invalidate_day (calendar, calendar->focus_row, + calendar->focus_col); } break; case GDK_KP_Down: case GDK_Down: return_val = TRUE; if (event->state & GDK_CONTROL_MASK) - gtk_calendar_set_year_next (calendar); + calendar_set_year_next (calendar); else { if (calendar->focus_row < 5) calendar->focus_row++; - gtk_calendar_paint_day (widget, old_focus_row, old_focus_col); - gtk_calendar_paint_day (widget, calendar->focus_row, - calendar->focus_col); + calendar_invalidate_day (calendar, old_focus_row, old_focus_col); + calendar_invalidate_day (calendar, calendar->focus_row, + calendar->focus_col); } break; case GDK_KP_Space: @@ -3244,139 +2724,113 @@ gtk_calendar_key_press (GtkWidget *widget, if (row > -1 && col > -1) { return_val = TRUE; - gtk_calendar_freeze (calendar); if (calendar->day_month[row][col] == MONTH_PREV) - gtk_calendar_set_month_prev (calendar); + calendar_set_month_prev (calendar); else if (calendar->day_month[row][col] == MONTH_NEXT) - gtk_calendar_set_month_next (calendar); + calendar_set_month_next (calendar); - gtk_calendar_select_and_focus_day (calendar, day); - - gtk_calendar_thaw (calendar); + calendar_select_and_focus_day (calendar, day); } } return return_val; } -static void -gtk_calendar_set_display_option (GtkCalendar *calendar, - GtkCalendarDisplayOptions flag, - gboolean setting) -{ - GtkCalendarDisplayOptions flags; - if (setting) - flags = calendar->display_flags | flag; - else - flags = calendar->display_flags & ~flag; - gtk_calendar_display_options (calendar, flags); -} + +/**************************************** + * Misc widget methods * + ****************************************/ -static gboolean -gtk_calendar_get_display_option (GtkCalendar *calendar, - GtkCalendarDisplayOptions flag) +static void +calendar_set_background (GtkWidget *widget) { - return (calendar->display_flags & flag) != 0; -} - - -static void -gtk_calendar_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkCalendar *calendar; + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + gint i; + + if (GTK_WIDGET_REALIZED (widget)) + { + for (i = 0; i < 4; i++) + { + if (priv->arrow_win[i]) + gdk_window_set_background (priv->arrow_win[i], + HEADER_BG_COLOR (widget)); + } + if (priv->header_win) + gdk_window_set_background (priv->header_win, + HEADER_BG_COLOR (widget)); + if (priv->day_name_win) + gdk_window_set_background (priv->day_name_win, + BACKGROUND_COLOR (widget)); + if (priv->week_win) + gdk_window_set_background (priv->week_win, + BACKGROUND_COLOR (widget)); + if (priv->main_win) + gdk_window_set_background (priv->main_win, + BACKGROUND_COLOR (widget)); + if (widget->window) + gdk_window_set_background (widget->window, + BACKGROUND_COLOR (widget)); + } +} - calendar = GTK_CALENDAR (object); +static void +gtk_calendar_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + if (previous_style && GTK_WIDGET_REALIZED (widget)) + calendar_set_background (widget); +} - switch (prop_id) +static void +gtk_calendar_state_changed (GtkWidget *widget, + GtkStateType previous_state) +{ + GtkCalendar *calendar = GTK_CALENDAR (widget); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + int i; + + if (!GTK_WIDGET_IS_SENSITIVE (widget)) { - case PROP_YEAR: - gtk_calendar_select_month (calendar, - calendar->month, - g_value_get_int (value)); - break; - case PROP_MONTH: - gtk_calendar_select_month (calendar, - g_value_get_int (value), - calendar->year); - break; - case PROP_DAY: - gtk_calendar_select_day (calendar, - g_value_get_int (value)); - break; - case PROP_SHOW_HEADING: - gtk_calendar_set_display_option (calendar, - GTK_CALENDAR_SHOW_HEADING, - g_value_get_boolean (value)); - break; - case PROP_SHOW_DAY_NAMES: - gtk_calendar_set_display_option (calendar, - GTK_CALENDAR_SHOW_DAY_NAMES, - g_value_get_boolean (value)); - break; - case PROP_NO_MONTH_CHANGE: - gtk_calendar_set_display_option (calendar, - GTK_CALENDAR_NO_MONTH_CHANGE, - g_value_get_boolean (value)); - break; - case PROP_SHOW_WEEK_NUMBERS: - gtk_calendar_set_display_option (calendar, - GTK_CALENDAR_SHOW_WEEK_NUMBERS, - g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + priv->in_drag = 0; + calendar_stop_spinning (calendar); } + + for (i = 0; i < 4; i++) + if (GTK_WIDGET_IS_SENSITIVE (widget)) + priv->arrow_state[i] = GTK_STATE_NORMAL; + else + priv->arrow_state[i] = GTK_STATE_INSENSITIVE; + + calendar_set_background (widget); } -static void -gtk_calendar_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +static void +gtk_calendar_grab_notify (GtkWidget *widget, + gboolean was_grabbed) { - GtkCalendar *calendar; + if (!was_grabbed) + calendar_stop_spinning (GTK_CALENDAR (widget)); +} - calendar = GTK_CALENDAR (object); +static gboolean +gtk_calendar_focus_out (GtkWidget *widget, + GdkEventFocus *event) +{ + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); - switch (prop_id) - { - case PROP_YEAR: - g_value_set_int (value, calendar->year); - break; - case PROP_MONTH: - g_value_set_int (value, calendar->month); - break; - case PROP_DAY: - g_value_set_int (value, calendar->selected_day); - break; - case PROP_SHOW_HEADING: - g_value_set_boolean (value, gtk_calendar_get_display_option (calendar, - GTK_CALENDAR_SHOW_HEADING)); - break; - case PROP_SHOW_DAY_NAMES: - g_value_set_boolean (value, gtk_calendar_get_display_option (calendar, - GTK_CALENDAR_SHOW_DAY_NAMES)); - break; - case PROP_NO_MONTH_CHANGE: - g_value_set_boolean (value, gtk_calendar_get_display_option (calendar, - GTK_CALENDAR_NO_MONTH_CHANGE)); - break; - case PROP_SHOW_WEEK_NUMBERS: - g_value_set_boolean (value, gtk_calendar_get_display_option (calendar, - GTK_CALENDAR_SHOW_WEEK_NUMBERS)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + calendar_stop_spinning (GTK_CALENDAR (widget)); + + priv->in_drag = 0; + return FALSE; } + +/**************************************** + * Drag and Drop * + ****************************************/ + static void gtk_calendar_drag_data_get (GtkWidget *widget, GdkDragContext *context, @@ -3396,163 +2850,548 @@ gtk_calendar_drag_data_get (GtkWidget *widget, g_free (date); } -/* Get/set whether drag_motion requested the drag data and - * drag_data_received should thus not actually insert the data, - * since the data doesn't result from a drop. - */ -static void -set_status_pending (GdkDragContext *context, - GdkDragAction suggested_action) -{ - g_object_set_data (G_OBJECT (context), - "gtk-calendar-status-pending", - GINT_TO_POINTER (suggested_action)); +/* Get/set whether drag_motion requested the drag data and + * drag_data_received should thus not actually insert the data, + * since the data doesn't result from a drop. + */ +static void +set_status_pending (GdkDragContext *context, + GdkDragAction suggested_action) +{ + g_object_set_data (G_OBJECT (context), + "gtk-calendar-status-pending", + GINT_TO_POINTER (suggested_action)); +} + +static GdkDragAction +get_status_pending (GdkDragContext *context) +{ + return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context), + "gtk-calendar-status-pending")); +} + +static void +gtk_calendar_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time) +{ + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + + priv->drag_highlight = 0; + gtk_drag_unhighlight (widget); + +} + +static gboolean +gtk_calendar_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget); + GdkAtom target; + + if (!priv->drag_highlight) + { + priv->drag_highlight = 1; + gtk_drag_highlight (widget); + } + + target = gtk_drag_dest_find_target (widget, context, NULL); + if (target == GDK_NONE) + gdk_drag_status (context, 0, time); + else + { + set_status_pending (context, context->suggested_action); + gtk_drag_get_data (widget, context, target, time); + } + + return TRUE; +} + +static gboolean +gtk_calendar_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GdkAtom target; + + target = gtk_drag_dest_find_target (widget, context, NULL); + if (target != GDK_NONE) + { + gtk_drag_get_data (widget, context, + target, + time); + return TRUE; + } + + return FALSE; +} + +static void +gtk_calendar_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + GtkCalendar *calendar = GTK_CALENDAR (widget); + guint day, month, year; + gchar *str; + GDate *date; + GdkDragAction suggested_action; + + suggested_action = get_status_pending (context); + + if (suggested_action) + { + set_status_pending (context, 0); + + /* We are getting this data due to a request in drag_motion, + * rather than due to a request in drag_drop, so we are just + * supposed to call drag_status, not actually paste in the + * data. + */ + str = gtk_selection_data_get_text (selection_data); + if (str) + { + date = g_date_new (); + g_date_set_parse (date, str); + if (!g_date_valid (date)) + suggested_action = 0; + g_date_free (date); + g_free (str); + } + else + suggested_action = 0; + + gdk_drag_status (context, suggested_action, time); + + return; + } + + date = g_date_new (); + str = gtk_selection_data_get_text (selection_data); + if (str) + { + g_date_set_parse (date, str); + g_free (str); + } + + if (!g_date_valid (date)) + { + g_warning ("Received invalid date data\n"); + g_date_free (date); + gtk_drag_finish (context, FALSE, FALSE, time); + return; + } + + day = g_date_get_day (date); + month = g_date_get_month (date); + year = g_date_get_year (date); + g_date_free (date); + + gtk_drag_finish (context, TRUE, FALSE, time); + + + g_object_freeze_notify (G_OBJECT (calendar)); + if (!(calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE) + && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)) + gtk_calendar_select_month (calendar, month - 1, year); + gtk_calendar_select_day (calendar, day); + g_object_thaw_notify (G_OBJECT (calendar)); +} + + +/**************************************** + * Public API * + ****************************************/ + +/** + * gtk_calendar_new: + * + * Creates a new calendar, with the current date being selected. + * + * Return value: a newly #GtkCalendar widget + **/ +GtkWidget* +gtk_calendar_new (void) +{ + return g_object_new (GTK_TYPE_CALENDAR, NULL); +} + +/** + * gtk_calendar_display_options: + * @calendar: a #GtkCalendar. + * @flags: the display options to set. + * + * Sets display options (whether to display the heading and the month headings). + * + * Deprecated: Use gtk_calendar_set_display_options() instead + **/ +void +gtk_calendar_display_options (GtkCalendar *calendar, + GtkCalendarDisplayOptions flags) +{ + gtk_calendar_set_display_options (calendar, flags); +} + +/** + * gtk_calendar_get_display_options: + * @calendar: a #GtkCalendar + * + * Returns the current display options of @calendar. + * + * Return value: the display options. + * + * Since: 2.4 + **/ +GtkCalendarDisplayOptions +gtk_calendar_get_display_options (GtkCalendar *calendar) +{ + g_return_val_if_fail (GTK_IS_CALENDAR (calendar), 0); + + return calendar->display_flags; +} + +/** + * gtk_calendar_set_display_options: + * @calendar: a #GtkCalendar + * @flags: the display options to set + * + * Sets display options (whether to display the heading and the month + * headings). + * + * Since: 2.4 + **/ +void +gtk_calendar_set_display_options (GtkCalendar *calendar, + GtkCalendarDisplayOptions flags) +{ + GtkWidget *widget = GTK_WIDGET (calendar); + GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar); + gint resize = 0; + gint i; + GtkCalendarDisplayOptions old_flags; + + g_return_if_fail (GTK_IS_CALENDAR (calendar)); + + old_flags = calendar->display_flags; + + if (GTK_WIDGET_REALIZED (widget)) + { + if ((flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE) + { + resize ++; + if (! (flags & GTK_CALENDAR_NO_MONTH_CHANGE) + && (priv->header_win)) + { + calendar->display_flags &= ~GTK_CALENDAR_NO_MONTH_CHANGE; + calendar_realize_arrows (calendar); + } + else + { + for (i = 0; i < 4; i++) + { + if (priv->arrow_win[i]) + { + gdk_window_set_user_data (priv->arrow_win[i], + NULL); + gdk_window_destroy (priv->arrow_win[i]); + priv->arrow_win[i] = NULL; + } + } + } + } + + if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING) + { + resize++; + + if (flags & GTK_CALENDAR_SHOW_HEADING) + { + calendar->display_flags |= GTK_CALENDAR_SHOW_HEADING; + calendar_realize_header (calendar); + } + else + { + for (i = 0; i < 4; i++) + { + if (priv->arrow_win[i]) + { + gdk_window_set_user_data (priv->arrow_win[i], + NULL); + gdk_window_destroy (priv->arrow_win[i]); + priv->arrow_win[i] = NULL; + } + } + gdk_window_set_user_data (priv->header_win, NULL); + gdk_window_destroy (priv->header_win); + priv->header_win = NULL; + } + } + + + if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES) + { + resize++; + + if (flags & GTK_CALENDAR_SHOW_DAY_NAMES) + { + calendar->display_flags |= GTK_CALENDAR_SHOW_DAY_NAMES; + calendar_realize_day_names (calendar); + } + else + { + gdk_window_set_user_data (priv->day_name_win, NULL); + gdk_window_destroy (priv->day_name_win); + priv->day_name_win = NULL; + } + } + + if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS) + { + resize++; + + if (flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS) + { + calendar->display_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS; + calendar_realize_week_numbers (calendar); + } + else + { + gdk_window_set_user_data (priv->week_win, NULL); + gdk_window_destroy (priv->week_win); + priv->week_win = NULL; + } + } + + if ((flags ^ calendar->display_flags) & GTK_CALENDAR_WEEK_START_MONDAY) + g_warning ("GTK_CALENDAR_WEEK_START_MONDAY is ignored; the first day of the week is determined from the locale"); + + calendar->display_flags = flags; + if (resize) + gtk_widget_queue_resize (GTK_WIDGET (calendar)); + + } + else + calendar->display_flags = flags; + + g_object_freeze_notify (G_OBJECT (calendar)); + if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING) + g_object_notify (G_OBJECT (calendar), "show-heading"); + if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES) + g_object_notify (G_OBJECT (calendar), "show-day-names"); + if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE) + g_object_notify (G_OBJECT (calendar), "no-month-change"); + if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS) + g_object_notify (G_OBJECT (calendar), "show-week-numbers"); + g_object_thaw_notify (G_OBJECT (calendar)); } -static GdkDragAction -get_status_pending (GdkDragContext *context) +/** + * gtk_calendar_select_month: + * @calendar: a #GtkCalendar + * @month: a month number between 0 and 11. + * @year: the year the month is in. + * + * Shifts the calendar to a different month. + * + * Return value: %TRUE, always + **/ +gboolean +gtk_calendar_select_month (GtkCalendar *calendar, + guint month, + guint year) { - return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context), - "gtk-calendar-status-pending")); -} + g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE); + g_return_val_if_fail (month <= 11, FALSE); + + calendar->month = month; + calendar->year = year; + + calendar_compute_days (calendar); + + gtk_widget_queue_draw (GTK_WIDGET (calendar)); -static void -gtk_calendar_drag_leave (GtkWidget *widget, - GdkDragContext *context, - guint time) -{ - GtkCalendarPrivateData *private_data; + g_object_freeze_notify (G_OBJECT (calendar)); + g_object_notify (G_OBJECT (calendar), "month"); + g_object_notify (G_OBJECT (calendar), "year"); + g_object_thaw_notify (G_OBJECT (calendar)); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - private_data->drag_highlight = 0; - gtk_drag_unhighlight (widget); - + g_signal_emit (calendar, + gtk_calendar_signals[MONTH_CHANGED_SIGNAL], + 0); + return TRUE; } -static gboolean -gtk_calendar_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time) +/** + * gtk_calendar_select_day: + * @calendar: a #GtkCalendar. + * @day: the day number between 1 and 31, or 0 to unselect + * the currently selected day. + * + * Selects a day from the current month. + **/ +void +gtk_calendar_select_day (GtkCalendar *calendar, + guint day) { - GtkCalendarPrivateData *private_data; - GdkAtom target; + g_return_if_fail (GTK_IS_CALENDAR (calendar)); + g_return_if_fail (day <= 31); - private_data = GTK_CALENDAR_PRIVATE_DATA (widget); - - if (!private_data->drag_highlight) + /* Deselect the old day */ + if (calendar->selected_day > 0) { - private_data->drag_highlight = 1; - gtk_drag_highlight (widget); + gint selected_day; + + selected_day = calendar->selected_day; + calendar->selected_day = 0; + if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) + calendar_invalidate_day_num (calendar, selected_day); } - target = gtk_drag_dest_find_target (widget, context, NULL); - if (target == GDK_NONE) - gdk_drag_status (context, 0, time); - else { - set_status_pending (context, context->suggested_action); - gtk_drag_get_data (widget, context, target, time); - } + calendar->selected_day = day; - return TRUE; + /* Select the new day */ + if (day != 0) + { + if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) + calendar_invalidate_day_num (calendar, day); + } + + g_object_notify (G_OBJECT (calendar), "day"); + + g_signal_emit (calendar, + gtk_calendar_signals[DAY_SELECTED_SIGNAL], + 0); } -static gboolean -gtk_calendar_drag_drop (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time) +/** + * gtk_calendar_clear_marks: + * @calendar: a #GtkCalendar + * + * Remove all visual markers. + **/ +void +gtk_calendar_clear_marks (GtkCalendar *calendar) { - GdkAtom target; - - target = gtk_drag_dest_find_target (widget, context, NULL); - if (target != GDK_NONE) + guint day; + + g_return_if_fail (GTK_IS_CALENDAR (calendar)); + + for (day = 0; day < 31; day++) { - gtk_drag_get_data (widget, context, - target, - time); - return TRUE; + calendar->marked_date[day] = FALSE; } - return FALSE; + gtk_widget_queue_draw (GTK_WIDGET (calendar)); } -static void -gtk_calendar_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time) +/** + * gtk_calendar_mark_day: + * @calendar: a #GtkCalendar + * @day: the day number to mark between 1 and 31. + * + * Places a visual marker on a particular day. + * + * Return value: %TRUE, always + **/ +gboolean +gtk_calendar_mark_day (GtkCalendar *calendar, + guint day) { - GtkCalendar *calendar = GTK_CALENDAR (widget); - guint day, month, year; - gchar *str; - GDate *date; - GdkDragAction suggested_action; - - suggested_action = get_status_pending (context); - - if (suggested_action) + g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE); + + if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == FALSE) { - set_status_pending (context, 0); - - /* We are getting this data due to a request in drag_motion, - * rather than due to a request in drag_drop, so we are just - * supposed to call drag_status, not actually paste in the - * data. - */ - str = gtk_selection_data_get_text (selection_data); - if (str) - { - date = g_date_new (); - g_date_set_parse (date, str); - if (!g_date_valid (date)) - suggested_action = 0; - g_date_free (date); - g_free (str); - } - else - suggested_action = 0; - - gdk_drag_status (context, suggested_action, time); - - return; + calendar->marked_date[day - 1] = TRUE; + calendar_invalidate_day_num (calendar, day); } + + return TRUE; +} - date = g_date_new (); - str = gtk_selection_data_get_text (selection_data); - if (str) - { - g_date_set_parse (date, str); - g_free (str); - } +/** + * gtk_calendar_unmark_day: + * @calendar: a #GtkCalendar. + * @day: the day number to unmark between 1 and 31. + * + * Removes the visual marker from a particular day. + * + * Return value: %TRUE, always + **/ +gboolean +gtk_calendar_unmark_day (GtkCalendar *calendar, + guint day) +{ + g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE); - if (!g_date_valid (date)) + if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == TRUE) { - g_warning ("Received invalid date data\n"); - g_date_free (date); - gtk_drag_finish (context, FALSE, FALSE, time); - return; + calendar->marked_date[day - 1] = FALSE; + calendar_invalidate_day_num (calendar, day); } + + return TRUE; +} - day = g_date_get_day (date); - month = g_date_get_month (date); - year = g_date_get_year (date); - g_date_free (date); +/** + * gtk_calendar_get_date: + * @calendar: a #GtkCalendar + * @year: location to store the year number, or %NULL + * @month: location to store the month number (between 0 and 11), or %NULL + * @day: location to store the day number (between 1 and 31), or %NULL + * + * Obtains the selected date from a #GtkCalendar. + **/ +void +gtk_calendar_get_date (GtkCalendar *calendar, + guint *year, + guint *month, + guint *day) +{ + g_return_if_fail (GTK_IS_CALENDAR (calendar)); + + if (year) + *year = calendar->year; + + if (month) + *month = calendar->month; + + if (day) + *day = calendar->selected_day; +} - gtk_drag_finish (context, TRUE, FALSE, time); +/** + * gtk_calendar_freeze: + * @calendar: a #GtkCalendar + * + * Does nothing. Previously locked the display of the calendar until + * it was thawed with gtk_calendar_thaw(). + **/ +void +gtk_calendar_freeze (GtkCalendar *calendar) +{ + g_return_if_fail (GTK_IS_CALENDAR (calendar)); +} - - g_object_freeze_notify (G_OBJECT (calendar)); - if (!(calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE) - && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)) - gtk_calendar_select_month (calendar, month - 1, year); - gtk_calendar_select_day (calendar, day); - g_object_thaw_notify (G_OBJECT (calendar)); +/** + * gtk_calendar_thaw: + * @calendar: + * + * Does nothing. Previously defrosted a calendar; all the changes made + * since the last gtk_calendar_freeze() were displayed. + **/ +void +gtk_calendar_thaw (GtkCalendar *calendar) +{ + g_return_if_fail (GTK_IS_CALENDAR (calendar)); } #define __GTK_CALENDAR_C__ diff --git a/gtk/gtkcalendar.h b/gtk/gtkcalendar.h index 162d814acc..3115e0ee0a 100644 --- a/gtk/gtkcalendar.h +++ b/gtk/gtkcalendar.h @@ -49,6 +49,8 @@ G_BEGIN_DECLS typedef struct _GtkCalendar GtkCalendar; typedef struct _GtkCalendarClass GtkCalendarClass; +typedef struct _GtkCalendarPrivate GtkCalendarPrivate; + typedef enum { GTK_CALENDAR_SHOW_HEADING = 1 << 0, @@ -77,8 +79,8 @@ struct _GtkCalendar GtkCalendarDisplayOptions display_flags; GdkColor marked_date_color[31]; - GdkGC *gc; - GdkGC *xor_gc; + GdkGC *gc; /* unused */ + GdkGC *xor_gc; /* unused */ gint focus_row; gint focus_col; @@ -86,7 +88,7 @@ struct _GtkCalendar gint highlight_row; gint highlight_col; - gpointer private_data; + GtkCalendarPrivate *priv; gchar grow_space [32]; /* Padding for future expansion */ @@ -141,9 +143,10 @@ void gtk_calendar_get_date (GtkCalendar *calendar, guint *year, guint *month, guint *day); +#ifndef GTK_DISABLE_DEPRECATED void gtk_calendar_freeze (GtkCalendar *calendar); void gtk_calendar_thaw (GtkCalendar *calendar); - +#endif G_END_DECLS diff --git a/gtk/gtkcellrenderer.c b/gtk/gtkcellrenderer.c index 8c6a8df773..596f6715f7 100644 --- a/gtk/gtkcellrenderer.c +++ b/gtk/gtkcellrenderer.c @@ -580,19 +580,13 @@ gtk_cell_renderer_render (GtkCellRenderer *cell, if (cell->cell_background_set && !selected) { - GdkColor color; - GdkGC *gc; - - color.red = priv->cell_background.red; - color.green = priv->cell_background.green; - color.blue = priv->cell_background.blue; - - gc = gdk_gc_new (window); - gdk_gc_set_rgb_fg_color (gc, &color); - gdk_draw_rectangle (window, gc, TRUE, - background_area->x, background_area->y, - background_area->width, background_area->height); - g_object_unref (gc); + cairo_t *cr = gdk_cairo_create (window); + + gdk_cairo_rectangle (cr, background_area); + gdk_cairo_set_source_color (cr, &priv->cell_background); + cairo_fill (cr); + + cairo_destroy (cr); } GTK_CELL_RENDERER_GET_CLASS (cell)->render (cell, diff --git a/gtk/gtkcellrendererpixbuf.c b/gtk/gtkcellrendererpixbuf.c index f3839ea791..f19adf6216 100644 --- a/gtk/gtkcellrendererpixbuf.c +++ b/gtk/gtkcellrendererpixbuf.c @@ -508,6 +508,7 @@ gtk_cell_renderer_pixbuf_render (GtkCellRenderer *cell, GdkPixbuf *colorized = NULL; GdkRectangle pix_rect; GdkRectangle draw_rect; + cairo_t *cr; priv = GTK_CELL_RENDERER_PIXBUF_GET_PRIVATE (cell); @@ -588,18 +589,13 @@ gtk_cell_renderer_pixbuf_render (GtkCellRenderer *cell, pixbuf = colorized; } - gdk_draw_pixbuf (window, - widget->style->black_gc, - pixbuf, - /* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */ - draw_rect.x - pix_rect.x, - draw_rect.y - pix_rect.y, - draw_rect.x, - draw_rect.y, - draw_rect.width, - draw_rect.height, - GDK_RGB_DITHER_NORMAL, - 0, 0); + cr = gdk_cairo_create (window); + + gdk_cairo_set_source_pixbuf (cr, pixbuf, pix_rect.x, pix_rect.y); + gdk_cairo_rectangle (cr, &draw_rect); + cairo_fill (cr); + + cairo_destroy (cr); if (invisible) g_object_unref (invisible); diff --git a/gtk/gtkcellrendererprogress.c b/gtk/gtkcellrendererprogress.c index a5b0d95ff7..c01bbd2f17 100644 --- a/gtk/gtkcellrendererprogress.c +++ b/gtk/gtkcellrendererprogress.c @@ -318,36 +318,41 @@ gtk_cell_renderer_progress_render (GtkCellRenderer *cell, guint flags) { GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell); - GdkGC *gc; PangoLayout *layout; PangoRectangle logical_rect; gint x, y, w, h, perc_w, pos; GdkRectangle clip; gboolean is_rtl; + cairo_t *cr; is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; - gc = gdk_gc_new (window); + cr = gdk_cairo_create (window); x = cell_area->x + cell->xpad; y = cell_area->y + cell->ypad; w = cell_area->width - cell->xpad * 2; h = cell_area->height - cell->ypad * 2; - - gdk_gc_set_rgb_fg_color (gc, &widget->style->fg[GTK_STATE_NORMAL]); - gdk_draw_rectangle (window, gc, TRUE, x, y, w, h); + + cairo_rectangle (cr, x, y, w, h); + gdk_cairo_set_source_color (cr, &widget->style->fg[GTK_STATE_NORMAL]); + cairo_fill (cr); x += widget->style->xthickness; y += widget->style->ythickness; w -= widget->style->xthickness * 2; h -= widget->style->ythickness * 2; - gdk_gc_set_rgb_fg_color (gc, &widget->style->bg[GTK_STATE_NORMAL]); - gdk_draw_rectangle (window, gc, TRUE, x, y, w, h); - gdk_gc_set_rgb_fg_color (gc, &widget->style->bg[GTK_STATE_SELECTED]); + cairo_rectangle (cr, x, y, w, h); + gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_NORMAL]); + cairo_fill (cr); + perc_w = w * MAX (0, cellprogress->priv->value) / 100; - gdk_draw_rectangle (window, gc, TRUE, is_rtl ? (x + w - perc_w) : x, y, perc_w, h); + + cairo_rectangle (cr, is_rtl ? (x + w - perc_w) : x, y, perc_w, h); + gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_SELECTED]); + cairo_fill (cr); layout = gtk_widget_create_pango_layout (widget, cellprogress->priv->label); pango_layout_get_pixel_extents (layout, NULL, &logical_rect); @@ -375,7 +380,7 @@ gtk_cell_renderer_progress_render (GtkCellRenderer *cell, layout); g_object_unref (layout); - g_object_unref (gc); + cairo_destroy (cr); } #define __GTK_CELL_RENDERER_PROGRESS_C__ diff --git a/gtk/gtkcellrenderertext.c b/gtk/gtkcellrenderertext.c index 9058c66357..343a4895fb 100644 --- a/gtk/gtkcellrenderertext.c +++ b/gtk/gtkcellrenderertext.c @@ -1626,29 +1626,22 @@ gtk_cell_renderer_text_render (GtkCellRenderer *cell, if (celltext->background_set && (flags & GTK_CELL_RENDERER_SELECTED) == 0) { - GdkColor color; - GdkGC *gc; + cairo_t *cr = gdk_cairo_create (window); + + if (expose_area) + { + gdk_cairo_rectangle (cr, expose_area); + cairo_clip (cr); + } + + gdk_cairo_rectangle (cr, background_area); + cairo_set_source_rgb (cr, + celltext->background.red / 65535., + celltext->background.green / 65535., + celltext->background.blue / 65535.); + cairo_fill (cr); - color.red = celltext->background.red; - color.green = celltext->background.green; - color.blue = celltext->background.blue; - - gc = gdk_gc_new (window); - - gdk_gc_set_rgb_fg_color (gc, &color); - - if (expose_area) - gdk_gc_set_clip_rectangle (gc, expose_area); - gdk_draw_rectangle (window, - gc, - TRUE, - background_area->x, - background_area->y, - background_area->width, - background_area->height); - if (expose_area) - gdk_gc_set_clip_rectangle (gc, NULL); - g_object_unref (gc); + cairo_destroy (cr); } if (priv->ellipsize_set) diff --git a/gtk/gtkcellview.c b/gtk/gtkcellview.c index 075c24e235..29ae5894b4 100644 --- a/gtk/gtkcellview.c +++ b/gtk/gtkcellview.c @@ -429,23 +429,16 @@ gtk_cell_view_expose (GtkWidget *widget, /* "blank" background */ if (cellview->priv->background_set) { - GdkGC *gc; + cairo_t *cr = gdk_cairo_create (GTK_WIDGET (cellview)->window); - gc = gdk_gc_new (GTK_WIDGET (cellview)->window); - gdk_gc_set_rgb_fg_color (gc, &cellview->priv->background); + gdk_cairo_rectangle (cr, &widget->allocation); + cairo_set_source_rgb (cr, + cellview->priv->background.red / 65535., + cellview->priv->background.green / 65535., + cellview->priv->background.blue / 65535.); + cairo_fill (cr); - gdk_draw_rectangle (GTK_WIDGET (cellview)->window, - gc, - TRUE, - - /*0, 0,*/ - widget->allocation.x, - widget->allocation.y, - - widget->allocation.width, - widget->allocation.height); - - g_object_unref (gc); + cairo_destroy (cr); } /* set cell data (if available) */ diff --git a/gtk/gtkcolorbutton.c b/gtk/gtkcolorbutton.c index 23f3758965..6ade7cefa0 100644 --- a/gtk/gtkcolorbutton.c +++ b/gtk/gtkcolorbutton.c @@ -59,7 +59,7 @@ struct _GtkColorButtonPrivate GdkPixbuf *pixbuf; /* Pixbuf for rendering sample */ GdkGC *gc; /* GC for drawing */ - GtkWidget *drawing_area;/* Drawing area for color sample */ + GtkWidget *draw_area; /* Widget where we draw the color sample */ GtkWidget *cs_dialog; /* Color selection dialog */ gchar *title; /* Title for the color selection window */ @@ -285,8 +285,8 @@ render (GtkColorButton *color_button) guint8 insensitive_g = 0; guint8 insensitive_b = 0; - width = color_button->priv->drawing_area->allocation.width; - height = color_button->priv->drawing_area->allocation.height; + width = color_button->priv->draw_area->allocation.width; + height = color_button->priv->draw_area->allocation.height; if (color_button->priv->pixbuf == NULL || gdk_pixbuf_get_width (color_button->priv->pixbuf) != width || gdk_pixbuf_get_height (color_button->priv->pixbuf) != height) @@ -378,8 +378,8 @@ expose_event (GtkWidget *widget, { GtkColorButton *color_button = GTK_COLOR_BUTTON (data); - gint width = color_button->priv->drawing_area->allocation.width; - gint height = color_button->priv->drawing_area->allocation.height; + gint width = color_button->priv->draw_area->allocation.width; + gint height = color_button->priv->draw_area->allocation.height; if (color_button->priv->pixbuf == NULL || width != gdk_pixbuf_get_width (color_button->priv->pixbuf) || @@ -389,15 +389,15 @@ expose_event (GtkWidget *widget, gdk_draw_pixbuf (widget->window, color_button->priv->gc, color_button->priv->pixbuf, - event->area.x, - event->area.y, + event->area.x - widget->allocation.x, + event->area.y - widget->allocation.y, event->area.x, event->area.y, event->area.width, event->area.height, GDK_RGB_DITHER_MAX, - event->area.x, - event->area.y); + event->area.x - widget->allocation.x, + event->area.y - widget->allocation.y); return FALSE; } @@ -480,7 +480,7 @@ gtk_color_button_drag_data_received (GtkWidget *widget, g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; - gtk_widget_queue_draw (color_button->priv->drawing_area); + gtk_widget_queue_draw (color_button->priv->draw_area); g_signal_emit (color_button, color_button_signals[COLOR_SET], 0); @@ -562,15 +562,16 @@ gtk_color_button_init (GtkColorButton *color_button) gtk_container_add (GTK_CONTAINER (alignment), frame); gtk_widget_show (frame); - color_button->priv->drawing_area = gtk_drawing_area_new (); + /* Just some widget we can hook to expose-event on */ + color_button->priv->draw_area = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); layout = gtk_widget_create_pango_layout (GTK_WIDGET (color_button), "Black"); pango_layout_get_pixel_extents (layout, NULL, &rect); - gtk_widget_set_size_request (color_button->priv->drawing_area, rect.width - 2, rect.height - 2); - g_signal_connect (color_button->priv->drawing_area, "expose_event", + gtk_widget_set_size_request (color_button->priv->draw_area, rect.width - 2, rect.height - 2); + g_signal_connect (color_button->priv->draw_area, "expose-event", G_CALLBACK (expose_event), color_button); - gtk_container_add (GTK_CONTAINER (frame), color_button->priv->drawing_area); - gtk_widget_show (color_button->priv->drawing_area); + gtk_container_add (GTK_CONTAINER (frame), color_button->priv->draw_area); + gtk_widget_show (color_button->priv->draw_area); color_button->priv->title = g_strdup (_("Pick a Color")); /* default title */ @@ -685,7 +686,7 @@ dialog_ok_clicked (GtkWidget *widget, gtk_widget_hide (color_button->priv->cs_dialog); - gtk_widget_queue_draw (color_button->priv->drawing_area); + gtk_widget_queue_draw (color_button->priv->draw_area); g_signal_emit (color_button, color_button_signals[COLOR_SET], 0); @@ -790,7 +791,7 @@ gtk_color_button_set_color (GtkColorButton *color_button, g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; - gtk_widget_queue_draw (color_button->priv->drawing_area); + gtk_widget_queue_draw (color_button->priv->draw_area); g_object_notify (G_OBJECT (color_button), "color"); } @@ -817,7 +818,7 @@ gtk_color_button_set_alpha (GtkColorButton *color_button, g_object_unref (color_button->priv->pixbuf); color_button->priv->pixbuf = NULL; - gtk_widget_queue_draw (color_button->priv->drawing_area); + gtk_widget_queue_draw (color_button->priv->draw_area); g_object_notify (G_OBJECT (color_button), "alpha"); } @@ -882,7 +883,7 @@ gtk_color_button_set_use_alpha (GtkColorButton *color_button, color_button->priv->use_alpha = use_alpha; render (color_button); - gtk_widget_queue_draw (color_button->priv->drawing_area); + gtk_widget_queue_draw (color_button->priv->draw_area); g_object_notify (G_OBJECT (color_button), "use-alpha"); } diff --git a/gtk/gtkcolorsel.c b/gtk/gtkcolorsel.c index c18b8afbdc..1f61d108f2 100644 --- a/gtk/gtkcolorsel.c +++ b/gtk/gtkcolorsel.c @@ -401,7 +401,7 @@ color_sample_draw_sample (GtkColorSelection *colorsel, int which) goff = priv->old_sample->allocation.width % 32; } - cr = gdk_drawable_create_cairo_context (da->window); + cr = gdk_cairo_create (da->window); wid = da->allocation.width; heig = da->allocation.height; @@ -427,23 +427,21 @@ color_sample_draw_sample (GtkColorSelection *colorsel, int which) if (which == 0) { - if (priv->has_opacity) - cairo_set_source_rgba (cr, - priv->old_color[COLORSEL_RED], - priv->old_color[COLORSEL_GREEN], - priv->old_color[COLORSEL_BLUE], - priv->has_opacity ? - priv->old_color[COLORSEL_OPACITY] : 1.0); + cairo_set_source_rgba (cr, + priv->old_color[COLORSEL_RED], + priv->old_color[COLORSEL_GREEN], + priv->old_color[COLORSEL_BLUE], + priv->has_opacity ? + priv->old_color[COLORSEL_OPACITY] : 1.0); } else { - if (priv->has_opacity) - cairo_set_source_rgba (cr, - priv->color[COLORSEL_RED], - priv->color[COLORSEL_GREEN], - priv->color[COLORSEL_BLUE], - priv->has_opacity ? - priv->color[COLORSEL_OPACITY] : 1.0); + cairo_set_source_rgba (cr, + priv->color[COLORSEL_RED], + priv->color[COLORSEL_GREEN], + priv->color[COLORSEL_BLUE], + priv->has_opacity ? + priv->color[COLORSEL_OPACITY] : 1.0); } cairo_rectangle (cr, 0, 0, wid, heig); @@ -615,11 +613,10 @@ palette_paint (GtkWidget *drawing_area, if (drawing_area->window == NULL) return; - cr = gdk_drawable_create_cairo_context (drawing_area->window); + cr = gdk_cairo_create (drawing_area->window); gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]); - cairo_rectangle (cr, - area->x, area->y, area->width, area->height); + gdk_cairo_rectangle (cr, area); cairo_fill (cr); if (GTK_WIDGET_HAS_FOCUS (drawing_area)) diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index 18c7d13be1..dec51ecff4 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -774,6 +774,8 @@ gtk_drag_highlight_expose (GtkWidget *widget, if (GTK_WIDGET_DRAWABLE (widget)) { + cairo_t *cr; + if (GTK_WIDGET_NO_WINDOW (widget)) { x = widget->allocation.x; @@ -792,11 +794,15 @@ gtk_drag_highlight_expose (GtkWidget *widget, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, widget, "dnd", x, y, width, height); - - gdk_draw_rectangle (widget->window, - widget->style->black_gc, - FALSE, - x, y, width - 1, height - 1); + + cr = gdk_cairo_create (widget->window); + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */ + cairo_set_line_width (cr, 1.0); + cairo_rectangle (cr, + x + 0.5, y + 0.5, + width - 1, height - 1); + cairo_stroke (cr); + cairo_destroy (cr); } return FALSE; diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 688b2a3cb8..b7b69420f9 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -3091,6 +3091,7 @@ gtk_entry_draw_text (GtkEntry *entry) if (GTK_WIDGET_DRAWABLE (entry)) { PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); + cairo_t *cr; gint x, y; gint start_pos, end_pos; @@ -3098,57 +3099,53 @@ gtk_entry_draw_text (GtkEntry *entry) get_layout_position (entry, &x, &y); - gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], - x, y, - layout); - + cr = gdk_cairo_create (entry->text_area); + + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]); + pango_cairo_show_layout (cr, layout); + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) { gint *ranges; gint n_ranges, i; PangoRectangle logical_rect; - GdkGC *selection_gc, *text_gc; - GdkRegion *clip_region; + GdkColor *selection_color, *text_color; pango_layout_get_pixel_extents (layout, NULL, &logical_rect); gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges); if (GTK_WIDGET_HAS_FOCUS (entry)) { - selection_gc = widget->style->base_gc [GTK_STATE_SELECTED]; - text_gc = widget->style->text_gc [GTK_STATE_SELECTED]; + selection_color = &widget->style->base [GTK_STATE_SELECTED]; + text_color = &widget->style->text [GTK_STATE_SELECTED]; } else { - selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE]; - text_gc = widget->style->text_gc [GTK_STATE_ACTIVE]; + selection_color = &widget->style->base [GTK_STATE_ACTIVE]; + text_color = &widget->style->text [GTK_STATE_ACTIVE]; } - - clip_region = gdk_region_new (); - for (i = 0; i < n_ranges; ++i) - { - GdkRectangle rect; - rect.x = INNER_BORDER - entry->scroll_offset + ranges[2 * i]; - rect.y = y; - rect.width = ranges[2 * i + 1]; - rect.height = logical_rect.height; - - gdk_draw_rectangle (entry->text_area, selection_gc, TRUE, - rect.x, rect.y, rect.width, rect.height); + for (i = 0; i < n_ranges; ++i) + cairo_rectangle (cr, + INNER_BORDER - entry->scroll_offset + ranges[2 * i], + y, + ranges[2 * i + 1], + logical_rect.height); - gdk_region_union_with_rect (clip_region, &rect); - } + cairo_clip (cr); - gdk_gc_set_clip_region (text_gc, clip_region); - gdk_draw_layout (entry->text_area, text_gc, - x, y, - layout); - gdk_gc_set_clip_region (text_gc, NULL); + gdk_cairo_set_source_color (cr, selection_color); + cairo_paint (cr); + + cairo_move_to (cr, x, y); + gdk_cairo_set_source_color (cr, text_color); + pango_cairo_show_layout (cr, layout); - gdk_region_destroy (clip_region); g_free (ranges); } + + cairo_destroy (cr); } } diff --git a/gtk/gtkhruler.c b/gtk/gtkhruler.c index f88dad5f27..acbceb6f74 100644 --- a/gtk/gtkhruler.c +++ b/gtk/gtkhruler.c @@ -177,7 +177,7 @@ gtk_hruler_draw_ticks (GtkRuler *ruler) 0, 0, widget->allocation.width, widget->allocation.height); - cr = gdk_drawable_create_cairo_context (ruler->backing_store); + cr = gdk_cairo_create (ruler->backing_store); gdk_cairo_set_source_color (cr, &widget->style->fg[widget->state]); cairo_rectangle (cr, @@ -296,7 +296,7 @@ gtk_hruler_draw_pos (GtkRuler *ruler) if ((bs_width > 0) && (bs_height > 0)) { - cairo_t *cr = gdk_drawable_create_cairo_context (widget->window); + cairo_t *cr = gdk_cairo_create (widget->window); /* If a backing store exists, restore the ruler */ if (ruler->backing_store) diff --git a/gtk/gtkhsv.c b/gtk/gtkhsv.c index 20ca50c63c..b73f59d7a4 100644 --- a/gtk/gtkhsv.c +++ b/gtk/gtkhsv.c @@ -1298,7 +1298,7 @@ gtk_hsv_expose (GtkWidget *widget, if (!gdk_rectangle_intersect (&event->area, &rect, &dest)) return FALSE; - cr = gdk_drawable_create_cairo_context (widget->window); + cr = gdk_cairo_create (widget->window); cairo_translate (cr, widget->allocation.x, widget->allocation.y); paint (hsv, cr, diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index 8bc4c74473..8494103682 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -1250,7 +1250,7 @@ gtk_icon_view_expose (GtkWidget *widget, if (expose->window != icon_view->priv->bin_window) return FALSE; - cr = gdk_drawable_create_cairo_context (icon_view->priv->bin_window); + cr = gdk_cairo_create (icon_view->priv->bin_window); cairo_set_line_width (cr, 1.); gtk_icon_view_get_drag_dest_item (icon_view, &path, &dest_pos); @@ -2899,7 +2899,7 @@ gtk_icon_view_paint_rubberband (GtkIconView *icon_view, fill_color_alpha / 255.); cairo_save (cr); - cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height); + gdk_cairo_rectangle (cr, &rect); cairo_clip (cr); cairo_paint (cr); @@ -6460,15 +6460,12 @@ gtk_icon_view_create_drag_icon (GtkIconView *icon_view, item->height + 2, -1); - cr = gdk_drawable_create_cairo_context (drawable); + cr = gdk_cairo_create (drawable); cairo_set_line_width (cr, 1.); - gdk_draw_rectangle (drawable, - widget->style->base_gc [GTK_WIDGET_STATE (widget)], - TRUE, - 0, 0, - item->width + 2, - item->height + 2); + gdk_cairo_set_source_color (cr, &widget->style->base_gc); + cairo_rectangle (cr, 0, 0, item->width + 2, item->height + 2); + cairo_fill (cr); area.x = 0; area.y = 0; @@ -6476,15 +6473,11 @@ gtk_icon_view_create_drag_icon (GtkIconView *icon_view, area.height = item->height; gtk_icon_view_paint_item (icon_view, cr, item, &area, - drawable, 1, 1, FALSE); + drawable, 1, 1, FALSE); - - gdk_draw_rectangle (drawable, - widget->style->black_gc, - FALSE, - 0, 0, - item->width + 1, - item->height + 1); + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */ + cairo_rectangle (cr, 0.5, 0.5, item->width + 1, item->height + 1); + cairo_stroke (cr); cairo_destroy (cr); diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index 7452c52e88..d2af4bf082 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -2900,14 +2900,13 @@ draw_arrow (GdkWindow *window, gint width, gint height) { - cairo_t *cr = gdk_drawable_create_cairo_context (window); + cairo_t *cr = gdk_cairo_create (window); gdk_cairo_set_source_color (cr, color); if (area) { - cairo_rectangle (cr, area->x, area->y, area->width, area->height); + gdk_cairo_rectangle (cr, area); cairo_clip (cr); - cairo_new_path (cr); } if (arrow_type == GTK_ARROW_DOWN) @@ -3611,7 +3610,7 @@ gtk_default_draw_check (GtkStyle *style, gint width, gint height) { - cairo_t *cr = gdk_drawable_create_cairo_context (window); + cairo_t *cr = gdk_cairo_create (window); enum { BUTTON, MENU, CELL } type = BUTTON; int exterior_size; int interior_size; @@ -3627,9 +3626,8 @@ gtk_default_draw_check (GtkStyle *style, if (area) { - cairo_rectangle (cr, area->x, area->y, area->width, area->height); + gdk_cairo_rectangle (cr, area); cairo_clip (cr); - cairo_new_path (cr); } exterior_size = MIN (width, height); @@ -3737,7 +3735,7 @@ gtk_default_draw_option (GtkStyle *style, gint width, gint height) { - cairo_t *cr = gdk_drawable_create_cairo_context (window); + cairo_t *cr = gdk_cairo_create (window); enum { BUTTON, MENU, CELL } type = BUTTON; int exterior_size; @@ -3751,9 +3749,8 @@ gtk_default_draw_option (GtkStyle *style, if (area) { - cairo_rectangle (cr, area->x, area->y, area->width, area->height); + gdk_cairo_rectangle (cr, area); cairo_clip (cr); - cairo_new_path (cr); } exterior_size = MIN (width, height); @@ -4543,7 +4540,7 @@ gtk_default_draw_focus (GtkStyle *style, sanitize_size (window, &width, &height); - cr = gdk_drawable_create_cairo_context (window); + cr = gdk_cairo_create (window); if (detail && !strcmp (detail, "colorwheel_light")) cairo_set_source_rgb (cr, 0., 0., 0.); @@ -4583,10 +4580,8 @@ gtk_default_draw_focus (GtkStyle *style, if (area) { - cairo_rectangle (cr, - area->x, area->y, area->width, area->height); + gdk_cairo_rectangle (cr, area); cairo_clip (cr); - cairo_new_path (cr); } cairo_rectangle (cr, @@ -4793,13 +4788,12 @@ gtk_default_draw_expander (GtkStyle *style, double x_double, y_double; gint degrees = 0; - cairo_t *cr = gdk_drawable_create_cairo_context (window); + cairo_t *cr = gdk_cairo_create (window); if (area) { - cairo_rectangle (cr, area->x, area->y, area->width, area->height); + gdk_cairo_rectangle (cr, area); cairo_clip (cr); - cairo_new_path (cr); } if (widget && diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index bbdf558a2c..f4d9140e32 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -7329,13 +7329,11 @@ text_window_invalidate_rect (GtkTextWindow *win, #if 0 { - GdkColor color = { 0, 65535, 0, 0 }; - GdkGC *gc = gdk_gc_new (win->bin_window); - gdk_gc_set_rgb_fg_color (gc, &color); - gdk_draw_rectangle (win->bin_window, - gc, TRUE, window_rect.x, window_rect.y, - window_rect.width, window_rect.height); - g_object_unref (gc); + cairo_t *cr = gdk_cairo_create (win->bin_window); + gdk_cairo_rectangle (cr, &window_rect); + cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); /* red */ + cairo_fill (cr); + cairo_destroy (cr); } #endif } diff --git a/gtk/gtkvruler.c b/gtk/gtkvruler.c index 648ec96143..c013aa557c 100644 --- a/gtk/gtkvruler.c +++ b/gtk/gtkvruler.c @@ -178,7 +178,7 @@ gtk_vruler_draw_ticks (GtkRuler *ruler) 0, 0, widget->allocation.width, widget->allocation.height); - cr = gdk_drawable_create_cairo_context (ruler->backing_store); + cr = gdk_cairo_create (ruler->backing_store); gdk_cairo_set_source_color (cr, &widget->style->fg[widget->state]); cairo_rectangle (cr, @@ -303,7 +303,7 @@ gtk_vruler_draw_pos (GtkRuler *ruler) if ((bs_width > 0) && (bs_height > 0)) { - cairo_t *cr = gdk_drawable_create_cairo_context (widget->window); + cairo_t *cr = gdk_cairo_create (widget->window); /* If a backing store exists, restore the ruler */ if (ruler->backing_store) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 72b78f939c..da8bbaa5b4 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -2744,7 +2744,25 @@ gtk_widget_queue_shallow_draw (GtkWidget *widget) g_return_if_fail (GTK_IS_WIDGET (widget)); + if (!GTK_WIDGET_REALIZED (widget)) + return; + gtk_widget_get_draw_rectangle (widget, &rect); + + /* get_draw_rectangle() gives us window coordinates, we + * need to convert to the coordinates that widget->allocation + * is in. + */ + if (!GTK_WIDGET_NO_WINDOW (widget) && widget->parent) + { + int wx, wy; + + gdk_window_get_position (widget->window, &wx, &wy); + + rect.x += wx; + rect.y += wy; + } + region = gdk_region_rectangle (&rect); gtk_widget_invalidate_widget_windows (widget, region); gdk_region_destroy (region); diff --git a/tests/testcairo.c b/tests/testcairo.c index 06257cd9af..918ebff974 100644 --- a/tests/testcairo.c +++ b/tests/testcairo.c @@ -197,7 +197,7 @@ on_expose_event (GtkWidget *widget, { cairo_t *cr; - cr = gdk_drawable_create_cairo_context (widget->window); + cr = gdk_cairo_create (widget->window); draw (cr, widget->allocation.width, widget->allocation.height); -- 2.30.2